I have an Android activitity with a spinner, a few buttons, and an EditText control. I want to apply text changes when the user taps anything outside the text editor. To achieve this I tried to implement onFocusChanged() listener in the following way:
textEditor.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, boolean hasFocus) {
if(!hasFocus)
{
checkUpdatedText();
}
}
});
Unfortunately, when I tap the spinner, the dropdown window appears, but the cursor is still visible in the text editor below it, and the onFocusChange() is not triggered. So the data in the dropdown list view is obsolete. Is there a way to ensure that the changes are applied exactly when another control is tapped? I do not want to update the data on every keypress, because this is a multiline edit view and the text may be lengthy.
Related
Alright,
When I have the focus on my EditText and the keyboard etc is showing. I click on my drawable at the end of the edittext (Cancel button). I recognize this event with an onTouchListener and hide the keyboard, clear focus, etc myself.
However, when I 'touch' the cancel button, it hides the keyboard but the focus stays on the edittext. Meaning the cursor is still showing, but not blinking. So when I click on the edittext again to get focus, it shows the option to copy/paste, etc like I'm long pressing the cursor and doesn't show the keyboard.
But when I 'press' the cancel button, it clears the focus, hides the keyboard and most importantly it hides the cursor resulting in completely removing the focus. Then when I click on the edittext again, it gets focus back and DOES show the keyboard.
What is this weird behavior and how do I make it that it always does the 'press' behavior.
my code:
searchView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (event.getRawX() >= searchView.getRight() - searchView.getCompoundDrawables()[2].getBounds().width()) {
hideKeyboard(v);
isSearching = false;
searchView.setText("");
searchView.clearFocus();
searchView.setFocusable(false);
searchView.setFocusableInTouchMode(false);
getView().requestFocus(); // parent has both focusables true
searchView.setFocusable(true);
searchView.setFocusableInTouchMode(true);
fetchArticles();
return true;
}
}
return false;
}
});
Like you're seeing, I'm trying everything I can to always get the same behavior. However no luck so far. Hope you guys can help me!
Try these in parent of that EditText or in views you want to touch:
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
It will allow to completely transfer focus elsewhere from EditText
However, in case when your drawable is inside of your Edittext like here:
android:drawableLeft="#drawable/my_icon"
the solution won't work until you make drawable as separate view in layout.
Oke so my current 'solution' is a suggested solution by #Dmitriy Pavlukhin.
Instead of using the drawableEnd from EditText itself, I created a separate view which has the same drawable and make sure to draw this on the same position. Now when I click this view, it clears the view as desired 100% of the time. The codebase is still the same from the question, however it is now implemented in a OnClick on the separated view.
I know there are a lot of similar questions out here
but I couldn't get any of the provided solutions working in a simple sample app.
The problem occurs when the softkeyboard is shown for the first time. As soon as it is shown, only by pressing the editText again makes it editable.
Tried the following:
android:windowSoftInputMode="adjustPan|adjustResize"
This is not solving any issues. It seems that this line is mandatory to have the activity resized after the softkeyboard is popping up. Unfortunately, it's also causing any EditTexts to lose focus. This is probably to the ListView itself gaining focus after the resizing process. So I tried the following workaround:
listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
This always causes the first visible EditText that the ListView contains to gain focus, which is undesirable. The second EditText in the second row should instead gain focus when pressed, which is not happening. Also, if I eventually managed to focus another EditText other then the first one shown (e.g. by pressing 'Next' on the softkeyboard), the first visible one will receive focus after the keyboard is dismissed and the ListView being resized to its full size again.
I tried several other things like intercepting onFocusChange() events for the ListView, while knowing which EditText was pressed by its TouchListener. Requesting the focus for that certain EditText again did not lead to any success either.
Using a ScrollView instead of a ListView as suggested by other users is not an option either for the concerned project.
A classic hack for situations like this is to use a handler and postDelayed(). In your adapter:
private int lastFocussedPosition = -1;
private Handler handler = new Handler();
public View getView(final int position, View convertView, ViewGroup parent) {
// ...
edittext.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 convertView;
}
This works on my device, but keep this code out of production. I also wouldn't be surprised if the focus bug manifests itself differently in different android versions or roms.
There are also many other problems with embedding an EditText within a ListView that have solutions that feel like a hack. See all of the other people struggling.
It's also very easy to have something like this happen:
.
After having gone down similar paths many times myself, I've mostly given up on trying to override any of the default keyboard behaviours or quirks. I would recommend trying to find alternative solution in your app if possible.
Have you considered having the ListView rows be just a styled TextView and then displaying a Dialog with an EditText when a row is clicked, updating the TextView as necessary?
I was having problems with the ActionBar "stealing" focus when I pressed on an EditText located within a ListView row. The above solutions did not work, but the following solution worked for me:
http://www.mysamplecode.com/2013/02/android-edittext-listview-loses-focus.html
Basically I added this to my ListView:
android:descendantFocusability="beforeDescendants"
and added this to my activity:
android:windowSoftInputMode="adjustPan"
Modify your manifest xml to add windowSoftInputMode in your activity:
<activity
android:name=".YourActivity"
android:windowSoftInputMode="adjustPan">
</activity>
I know its a very old thread but this answer might be helpful to someone so here it is:
Switch to RecyclerView and you won't have to worry about these annoying issues of ListView. Instead of making new view it recycles and reuses old views.
I was having the same problem with recyclerView and trying all suggested solutions.
Finally, the problem on my case was that the recyclerView had wrap_content as value for the height on my XML by accident; changed it to match_parent and started working as expected, no focusable value set and using android:windowSoftInputMode="adjustResize"
Use Recycler View, this solves several issues from list and gridview. You can even work with staggered gridviews. You could easily start working with this.
When the list is long enough to cover the soft keyboard, the
EditText in Listview loses focus when pressed on Android 4.x.
One solution is to wrap the Listview in a linear layout with a height of half the screen.
Whenever the Listview doesn't cover the softkeyboard, everything is fine.
was having the same issue. Searched for all such solutions with inputMode, focusability et al. Best solution, migrate to recycler view.
In my case I've added local value currentlyFocusedRow in my Adapter.
In the method getView() I've add these code to each editText:
if (currentlyFocusedRow == position) {
editText.requestFocus();
}
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
if (currentlyFocusedRow == -1) {
currentlyFocusedRow = position;
}
} else {
currentlyFocusedRow = -1;
}
}
});
I have a EditText where user needs to enter date. For date picking I have a custom wheel view (like iOS). Now on click of date EditText, I want to open a soft keyboard like drawer from bottom & put that wheel view inside it.
So can I replace the soft keyboard with my wheel view ? I mean, the container which hold the keyboard should now hold my custom wheel view.
Is there any way to achieve that ? Or any other better option for my purpose ?
1) If you must use EditText, you can prevent keyboard coming up, by setting its input type correctly. Other answer already mentions that.
2) But why use EditText here, especially since you are not inputing any value using keyboard here. You can use a TextView, and its onClickListener you can animate a LinearLayout (containing date picker) upwards.
yourTextView.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
//Animate a LinearLayout containing a DatePicker
animateDatePickerView();
}
});
Depending on your requirements and how re-usable you want it to be.
For the simple way, you can create a view to host that wheel picker align it bottom of the root layout and just hide/show it with some animation.
First you would want to override the onTouchListener of your edit text, consume the event and do what you want there.
editText.setOnTouchListener(new OnTouchListener() {
public boolean onTouch (View v, MotionEvent event) {
//Show the wheely wheel.
return true; //Consume the event.
}
});
My personal idea (not tested)
prevent showing keyboard when edittext is focused.
E.g, setInputType(InputType.TYPE_NULL);
Use a customized activity which contains your wheel and show it as dialog ( set theme as dialog).
I have a simple layout with EditText and a Listview. Implemented custom ArrayList adapter to fill in the listview and custom filter so user can search for items displayed in the listview.
When I run the application, the focus is initially set to EditText and the keyboard is displayed as expected. But here is what I want to do:
The focus should be initially set to ListView when the app is launched.
If the user wants to enter text by selecting edittext control, then the keyboard should appear.
( At this point as the user inputs text, the listview items will change - I already implmented this)
With the keyboard still open, if the user select an item in the listview, the keyboard should disappear and trigger the listview onItemClick function.
How can I accomplish this?
1.Add below attribute to your particular EditText in its layout-xml:
android:focusable="false"
android:focusableInTouchMode="true"
2.Then in your Activity add:
mEditText.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
v.setFocusable(true);
return false;
}
});
Hope this helps.
In my application I need to make something happen when an EditText loses its focus. When editing an EditText I can't make it lose its focus. In windows phone there is the this.Focus(); method but here in android it doesn't seem to be the same. How can I do???
To focus away from Edit Text one should use clearFocus();
Now comes if you do need to handle any particular event if the focus is changed then..
**use Focus Change listener on view.**
onFocusChange(View v, boolean hasFocus)
//Called when the focus state of a view has changed.
if(!hasfocus)
{
//Your piece of code if the focus is lost on text view..
}