Edit text loosing focus after typing something - android

I am inflating edit text in adapter class within of a list view. View is looking cool multiple edit text are appearing properly but when I do focus on the edit text or if I try to type something it loosing focus I tried to adding listeners, changing manifest file but nothing works for me.
following code is not working for me
#Override
public View getChildView(int position, int i1, boolean b, View view,
ViewGroup viewGroup) {
EditText comment = view.findViewById(R.id.txtRecordComment);
comment.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (lastFocussedPosition == -1 || lastFocussedPosition == position) {
lastFocussedPosition = position;
edittext.requestFocus();
}
}
}, 200);
} else {
lastFocussedPosition = -1;
}
}
});
return view;
}
please help me to resolve this issue

Since you are using a ListView, it is bound to happen with your current code implementation.
You must remember that if your EditText is in a ListView, every key down will result in the edit text losing and getting focus because all the views are redrawn, so the edit text representing whatever row used to be focused is now a completely different object.
To get the expected behaviour, declare a variable in your adapter: int focusedRow. In getView method of your adapter, add an onFocusChanged listener to the EditText and when that edit text gains focus, set focusedRow = whatever row the focused EditText happens to be in.
Also set any edit text that is in the currentlyFocusedRow to be focused.
Update:
If you have multiple EditTexts, add an onFocusChanged listener to each edit text.

Add below code in Android Manifest file
<activity android:name=".ActivityName"
android:label="#string/app_name"
android:windowSoftInputMode="adjustPan">
Hope this will work

Related

How to properly get & set text to editText in expandable recycler view

i'm working with expandable recycler view from bignerdranch. Inside my child view, i placed a edit text where user can leave a comment regarding an issue shown on the parent view.
My problem is that, i wanted the user input to be save after the edit text loose focus. (In this case, i have 3 parents, and each parent has 1 editText). But when i input edit text 1 and focus on edit text 2 without inputing... edit text 2 would take up edit text 1 input after it loose focus.
I try using text watcher, and put the codes inside after text changes.. but the app freezes and stopped working after a while. If there a better way for me to save accordingly?
mCatatan is my editText.
#Override
public void onBindChildViewHolder(final ATPChildViewHolder atpChildViewHolder, int i, Object childObject) {
final ATPChild atpChild = (ATPChild) childObject;
final String text = atpChildViewHolder.mCatatanInput.getText().toString();
if(!text.equals("")) {
atpChild.setDetail(text);
atpChildViewHolder.mCatatanInput.setText(atpChild.getDetail());
} else {
atpChildViewHolder.mCatatanInput.setText(atpChild.getDetail());
}
// todo: fixed catatan being saved to another catatan
atpChildViewHolder.mCatatanInput.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
Log.d(TAG, "onFocusChange: ");
atpChild.setDetail(atpChildViewHolder.mCatatanInput.getText().toString());
atpChildViewHolder.mCatatanInput.setText(atpChild.getDetail());
}
}
});
}

Multiple EditText in ListView, tap to focus on one EditText and focus jumps to the first

I've got EditTexts in my rows in a ListView. When I tap on one of the EditTexts the soft keyboard appears and the focus jumps to the first EditText in the list instead of staying in the field where I tapped.
Here is a video of it:
https://youtu.be/ZwuFrX-WWBo
I created a completely stripped down app to demonstrate the problem. The full code is here: https://pastebin.com/YT8rxqKa
I'm not doing anything to alter the focus in my code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.cell_textfield, parent, false);
}
TextView label = (TextView) convertView.findViewById(R.id.textview1);
EditText textfield = (EditText) convertView.findViewById(R.id.textview2);
String text = String.format("Row %d", position);
label.setText(text);
textfield.setText(text);
return convertView;
}
I found another post on StackOverflow giving a workaround for this dumb Android behavior, which involves putting an OnFocusChangedListener on all of the textfields so they can retake focus if it's taken from them improperly.
That worked to regain focus, but then I discovered that when a textfield retakes focus the cursor ends up at the start of the text instead of end, which is unnatural and annoying to my users.
Here is a video of that:
https://youtu.be/A35wLqbuIac
Here's the code for that OnFocusChangeListener. It works to fight the stupid Android behavior of moving focus, but the cursor is misplaced after it regains focus.
View.OnFocusChangeListener onFocusChangeListener = new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
long t = System.currentTimeMillis();
long delta = t - focusTime;
if (hasFocus) { // gained focus
if (delta > minDeltaForReFocus) {
focusTime = t;
focusTarget = view;
}
}
else { // lost focus
if (delta <= minDeltaForReFocus && view == focusTarget) {
focusTarget.post(new Runnable() { // reset focus to target
public void run() {
Log.d("BA", "requesting focus");
focusTarget.requestFocus();
}
});
}
}
}
};
I hate having to put a bandaid on a bandaid on a bandaid to try to get Android to just behave as it would naturally be expected to behave, but I'll take what I can get.
1) Is there something I can do to fix this problem at the source and not have to have the OnFocusChangeListener at all?
2) If (1) isn't possible, then how can I make sure that when I force focus back to the correct field that I make sure the cursor is placed at the end? I tried using setSelection() right after requestFocus() but since the textfield wasn't yet focused the selection is ignored.
Here was my "solution." In short: ListViews are stupid and will always be a total nightmare when EditTexts are involved, so I changed my Fragment/Adapter code to be able to adapt to either a ListView layout or a ScrollView layout. It only works if you have a small number of rows, because the scrollview implementation isn't able to take advantage of lazy-loading and view recycling. Thankfully, any situation wherein I want EditTexts in a ListView, I rarely have more than 20 rows or so.
When inflating my view in my BaseListFragment, I get my layout id via a method that relies on a hasTextFields() method:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(getLayoutId(), container, false);
return view;
}
public boolean hasTextfields() {
return false;
}
public int getLayoutId() {
if (hasTextfields()) {
return R.layout.scrollfragment;
} else {
return R.layout.listfragment;
}
}
In my various subclasses of my BaseListFragment, if I need to have an EditText in one of my fields, I just override the hasTextFields() method to return true and then my fragment/adapter switchs over to using the basic scrollview implementation.
From there, it's a matter of making sure that the Adapter handles the standard ListView actions for both the ListView and the ScrollView scenarios. Like this:
public void notifyDataSetChanged() {
// If scrollContainer is not null, that means we're in a ScrollView setup
if (this.scrollContainer != null) {
// intentionally not calling super
this.scrollContainer.removeAllViews();
this.setupRows();
} else {
// use the real ListView
super.notifyDataSetChanged();
}
}
public void setupRows() {
for (int i = 0; i < this.getCount(); i++) {
View view = this.getView(i, null, this.scrollContainer);
view.setOnClickListener(myItemClickListener);
this.scrollContainer.addView(view);
}
}
One issue that the click listener presented is that a ListView wants an AdapterView.OnItemClickListener, but arbitrary Views inside a ScrollView want a simple View.OnClickListener. So, I made my ItemClickListener also implement View.OnClickListener and then just dispatched the OnClick to the OnItemClick method:
public class MyItemClickListener implements AdapterView.OnItemClickListener, View.OnClickListener {
#Override
public void onClick(View v) {
// You can either have your Adapter set the tag on the View to be its position
// or you could have your click listener use v.getParent() and iterate through
// the children to find the position. I find its faster and easier to have my
// adapter set the Tag on the view.
int position = v.getTag();
this.onItemClick(null, v, config.getPosition(), 0);
}
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// ...
}
}
Then in MyEditTextListFragment, I create the adapter like this:
listener = createClickListener();
adapter = createListAdapter();
if (scrollContainer != null) {
adapter.setScrollContainer(scrollContainer);
adapter.setMenuItemClickListener(listener);
adapter.setupRows();
} else {
getListView().setOnItemClickListener(listener);
getListView().setAdapter(adapter);
}
Here is my scrollfragment.xml for reference:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:clickable="true"
>
<!--
The following LinearLayout as a focus catcher that won't cause the keyboard to
show without it, the virtual keyboard shows up immediately/always which means we
never get to the enjoy the full size of our screen while scrolling, and
that sucks.
-->
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="0px"
android:layout_height="0px"/>
<!--
This ListView is still included in the layout but set to visibility=gone. List
fragments require a standard ListView in the layout, so this gets us past that
check and allows us to use the same adapter code in both listview and scrollview
situations.
-->
<ListView android:id="#id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawSelectorOnTop="false"
android:background="#null"
android:layout_alignParentTop="true"
android:descendantFocusability="afterDescendants"
android:visibility="gone"
/>
<!--
This scrollview will act as our fake listview so that we don't have to deal with
all the stupid crap that comes along with having EditTexts inside a ListView.
-->
<ScrollView
android:id="#+id/scrollView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="afterDescendants"
>
<LinearLayout
android:id="#+id/scrollContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
</LinearLayout>
</ScrollView>
</RelativeLayout>
Try this once, it worked for me:
public void setCursorPosition() {
focusTarget.requestFocus();
focusTarget.setCursorVisible(true);
other.setCursorVisible(false);
} else {
other.setCursorVisible(true);
focusTarget.setCursorVisible(false);
}
}

Check if dynamically added TextEdit has text in it Android

I'm overriding the onFocusChanged to pinpoint the TextEdit that just lost focus. The point is to remove this TextEdit if it doesn't have any text in it. The problem is that the if((EditText... is not valid. I get cannot resolve method 'getText()'. I've tried casting it to tell that it's a EditText view.
listItemsView is the id of the LinearLayout and listItems is an ArrayList of EditText.
#Override
public void onFocusChange(View view, boolean hasFocus) {
if (!hasFocus) {
int removeCurrent = listItems.indexOf(this)+1;
// code to execute when EditText loses focus
if((EditText)view.getText().equals("")) {
}
listItemsView.removeViewAt(removeCurrent);
listItems.remove(removeCurrent);
}
}
I've also tried:
if((EditText)listItemsView.getChildAt(removeCurrent).getText().equals(""))
And got the same result.
When you want to cast a value to a type, you do this:
(T)V
Where T is the type you want to cast to, and V is the value.
So far so good?
In your code,
(EditText)view.getText().equals("")
What is V and what is T? The answer might surprise you! T is obviously EditText, but V here is actually view.getText().equals("")!
In other words, you did not cast view to EditText. That's why the compiler can't find a method named getText. To tell the compiler to specifically cast view, add parentheses:
((EditText)view).getText().equals("")

EditText - change background color of text (and only text - not the whole view)

When a user enters information in an EditText, and moves to the next EditText, the information is highlighted as shown below:
The code for this:
edittext.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
v.setBackgroundColor(Color.WHITE);
((EditText) v).setTextColor(Color.BLACK);
} else {
//v.setBackgroundColor(Color.LTGRAY); //also works like this
((EditText) v).setBackgroundColor(Color.LTGRAY);
((EditText) v).setTextColor(Color.BLACK);
}
}
});
Which is called in the onCreate method like this:
edittext = (EditText) findViewById(R.id.editText1);
However, It would be much better if the background color only applied to the text itself, rather than the view, like this (from the gmail app):
Does anybody have any suggestions on how to apply the background color to the text only (not the whole EditText view) as above?
Thanks.
You can achieve what you want by using a BackgroundColorSpan. You can find more information here:
http://developer.android.com/reference/android/text/style/BackgroundColorSpan.html
To use spans you need to build a SpannableString which you can do using a SpannableStringBuilder:
http://developer.android.com/reference/android/text/SpannableStringBuilder.html

EditText in ListView hidden by keyboard when focused

I have a ListView containing rows with EditText's.
When I click on an EditText and it's not already focused it receives focus, the keyboard appears and the EditText is moved above the CandidateView (desired behaviour).
However when I make a key press, the EditText maintains focus and receives the input but moves down and is obscured by the keyboard (the previous movement is reversed).
When I click on the EditText when it is already selected without the keyboard shown, the keyboard pops up but the EditText is not moved to the right position (above the CandidateView). It still receives the input.
I add a header view containing EditText's and there everything works correctly.
This is the code of my ArrayAdapter where the row view is created:
View view = inflater.inflate(R.layout.row_profile_entry_text, null);
final String question = getItem(position);
TextView textViewQuestion = (TextView) view.findViewById(R.id.rpeq_TextViewQuestion);
textViewQuestion.setText(question);
final EditText editTextAnswer = (EditText) view.findViewById(R.id.rpeq_EditTextAnswer);
editTextAnswer.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
mAnswers.put(question, s.toString());
}
});
if (mAnswers.containsKey(question)) {
editTextAnswer.setText(mAnswers.get(question));
}
return view;
I would also like to emphasize that I already added
android:windowSoftInputMode="adjustPan" to the Manifest and android:descendantFocusability="beforeDescendants" to the ListView as most of the answers to other questions suggest.
Without adjustPan the EditText is not able to receive focus at all but it does not solve the issue entirely.
Does someone have an idea what I am doing wrong?
Try this:
<activity name="YourActivity"
android:windowSoftInputMode="stateVisible|adjustResize|adjustPan">
</activity>
in the manifest file.
Most probably, adjustResize must work, if you are using a ScrollView.
after many hours spent on this problem this is my solution (for Android < 4.2):
1) Manifest => android:windowSoftInputMode="adjustPan"
2) Activity=> create OnTouchListner and pass to Adapter
private OnTouchListener exampleOnTouchListener = new OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_UP == event.getAction()) {
int position = (Integer) v.getTag();
myListView.setSelection(position);
}
return false;
}
};
3) Adapter
if (exampleOnTouchListener!= null) {
myEditText.setTag(position);
myEditText.setOnTouchListener(exampleOnTouchListener);
// if last element set padding bottom for spacing
if (position == items.size() - 1) {
LinearLayout myLinearLayout = (LinearLayout) convertView
.findViewById(R.id.ticketcontolProposedRealvalueLinearLayout);
myLinearLayout.setPadding(0, 0, 0,SET_PADDING_BOTTOM);
}
}

Categories

Resources