Android Keyboard Not Appearing, Even When Explicitly Requested
Solution 1:
I've now been able to figure this out. By looking at the code for InputMethodManager.showSoftInput(View, int)
, I worked out that my request to bring up the keyboard was being ignored because the view I was passing wasn't the InputMethodManager's active view.
To solve my problem, I added two new fields to the MyActivity
class, namely:
private EditText search_edit_text;
privateboolean mySearchView_editflag;
The search_edit_text
variable will be the view inside the SearchView mySearchView
which is the view that actually gets the focus and receives the input from the keyboard. The mySearchView_editflag
will normally be false, but it will be true
when the app is waiting for the right time to bring up the keyboard.
To get hold of the search_edit_text
EditText object I used the following function
publicstatic EditText GetEditText(ViewGroup vg) {
for(int i=0; i< vg.getChildCount(); i++) {
Viewv= vg.getChildAt(i);
if (v instanceof EditText) {
return (EditText)v;
} elseif (v instanceof ViewGroup) {
EditTextet= GetEditText((ViewGroup)v);
if (et != null) return et;
}
}
returnnull;
}
and altered my onCreateOptionsMenu(Menu)
function to include the following
DestinationTxt = menu.findItem(R.id.actionbar_search);mySearchView = (SearchView)DestinationTxt.getActionView();search_edit_text = GetEditText(mySearchView);mySearchView_editflag = false;
This initializes the search_edit_text
and mySearchView_editflag
variables. My onResume()
method was altered to
@OverridepublicvoidonResume() {
super.onResume();
if (startsearch) {
DestinationTxt.expandActionView();
mySearchView_editflag = true;
}
}
and I included code which calls the following method at high frequency:
publicvoidCheckStatus() {
if (mySearchView_editflag && imm.isActive(search_edit_text)) {
imm.showSoftInput(search_edit_text, 0);
mySearchView_editflag=false;
}
}
This app now works as I want it to, because following the activity switch when search input in the actionbar is required, the app now waits until imm.isActive(search_edit_text)
is true (which means the EditText
object is receiving input) before calling imm.showSoftInput(search_edit_text, 0)
to make sure that the keyboard is visible.
To help me work all this out, I used InputMethodManager.showSoftInput(View, int, ResultReceiver)
instead of InputMethodManager.showSoftInput(View, int)
, so instead of
imm.showSoftInput(search_edit_text, 0);
I had
ImmResultsReceiverirr=newImmResultsReceiver();
imm.showSoftInput(search_edit_text, 0, irr);
where ImmResultsReceiver
is the class
publicclassImmResultsReceiverextendsResultReceiver {
publicImmResultsReceiver() { super(null); }
@OverrideprotectedvoidonReceiveResult(int resultCode, Bundle resultData) {
String descrip;
switch(resultCode) {
case InputMethodManager.RESULT_UNCHANGED_SHOWN: descrip = "RESULT_UNCHANGED_SHOWN"; break;
case InputMethodManager.RESULT_UNCHANGED_HIDDEN: descrip = "RESULT_UNCHANGED_HIDDEN"; break;
case InputMethodManager.RESULT_SHOWN: descrip = "RESULT_SHOWN"; break;
case InputMethodManager.RESULT_HIDDEN: descrip = "RESULT_HIDDEN"; break;
default:descrip="InputMethodManager("+resultCode+")"; break;
}
Log.d("MyLog", "ImmResultsReceiver,"+descrip+","+(resultData == null?"":"resultData.size()="+resultData.size()));
}
}
If the ImmResultsReceiver.onReceiveResult(...)
method is never called, it means that the call to InputMethodManager.showSoftInput(...)
has been ignored because the view that's passed to InputMethodManager.showSoftInput(...)
isn't the InputMethodManager's active view.
Solution 2:
Inside your manifest file, try adding the following to the MyActivity activity section to show the keyboard when the activity starts:
android:windowSoftInputMode="stateVisible"
This should cause the keyboard to become visible when the activity starts.
edit
then try this inside onCreateOptionsMenu
..
@OverridepublicbooleanonCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.action_menu, menu);
MenuItem menu_search = menu.findItem(actionbar_search);
menu_search.setOnActionExpandListener(newOnActionExpandListener() {
@OverridepublicbooleanonMenuItemActionCollapse(MenuItem item) {
// Do something when collapsedreturntrue; // Return true to collapse action view
}
@OverridepublicbooleanonMenuItemActionExpand(MenuItem item) {
//get focus
item.getActionView().requestFocus();
//get input methodInputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
returntrue; // Return true to expand action view
}
});
returntrue;
}
Solution 3:
A postscript to my last input. Before I postDelayed the toggle I checked InputMethodManager.isActive() for false. All well and good except that after 350 ms it no longer applied. So in your postDelayed, when your delayed code runs, check again for InputMethodManager.isActive() and if true do not toggle just showSoftInput otherwise the newly visible keyboard will go away, which is not what one wants at all.
Solution 4:
Oops, I think I posted my postscript to a related thread, not the original, however what I am talking about comes when one's app has been forced into the background by a phone call for instance and when it comes back EVEN if you explicitly find the EditText that had the focus and try and bring up the soft keyboard it simply won't come up. So here is the snippet of code that I employed after reading about posting the Toggle...
Note that the "O" referenced here is simply a class of static objects that I use in my app and the imeListener is a callback I use to tell the Fragments stuff about what's happening...
if (O.mInputMethodManager.isActive()) {
if (imeListener != null) {
O.mInputMethodManager.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT,
newResultReceiver(handler) {
protectedvoidonReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == InputMethodManager.RESULT_SHOWN || resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN) {
imeListener.onSoftKeyboardShown(filenameEditText);
}
}
}
);
}
else {
O.mInputMethodManager.showSoftInput(this, InputMethodManager.SHOW_IMPLICIT);
}
}
else { // there will be a slight delay...
handler.postDelayed(newRunnable() {
@Overridepublicvoidrun() {
if (!O.mInputMethodManager.isActive()) { // come right?
O.mInputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
}
if (imeListener != null) {
O.mInputMethodManager.showSoftInput(filenameEditText, InputMethodManager.SHOW_IMPLICIT,
newResultReceiver(handler) {
protectedvoidonReceiveResult(int resultCode, Bundle resultData) {
if (resultCode == InputMethodManager.RESULT_SHOWN || resultCode == InputMethodManager.RESULT_UNCHANGED_SHOWN) {
imeListener.onSoftKeyboardShown(filenameEditText);
}
}
}
);
} else {
O.mInputMethodManager.showSoftInput(filenameEditText, InputMethodManager.SHOW_IMPLICIT);
}
}
}, 350);
}
Solution 5:
This is an old question, but I ran into a similar problem where the view has focus, but is not active in the InputMethodManager. I took a queue from some of the answers above by simply adding a delay after requestFocus(). Since I'm using Kotlin, I used a coroutine to implement the delay. That way we are not blocking the main thread. Relevant code is shown below.
Class SomeActivity : AppCompatActivity(), CoroutineScope {
// Create a coroutine jobprivateval job = Job()
// Implement CoroutineScopeoverrideval coroutineContext: CoroutineContext
get() = Dispatchers.Main + job
// Cancel the job when the activity is destroyedoverridefunonDestroy() {
super.onDestroy()
job.cancel()
}
// Shows the keyboard when view has focusprivatefunshowKeyboard(view: View) {
// start a coroutine
launch {
withContext(Dispatchers.Main) {
// add delay of 300ms
delay(300)
if (currentFocus == view) {
// show the keyboard if view still has focus
(getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
.showSoftInput(view, InputMethodManager.SHOW_IMPLICIT)
}
}
}
}
}
Post a Comment for "Android Keyboard Not Appearing, Even When Explicitly Requested"