Button to capture back from the soft keyboard

I have activity with several input fields. When the activity starts, a soft keyboard is displayed. When the back button is pressed, the soft keyboard closes and to close the activity I need to press the back button again.

So the question is: is it possible to intercept the "Back" button to close the soft keyboard and complete the operation with one click of the "Back" button without creating a custom InputMethodService ?

PS I know how to intercept the return button in other cases: onKeyDown() or onBackPressed() , but in this case it does not work: only the second press of the return button is intercepted.

+68
android
Oct 15 '10 at 6:59
source share
8 answers

Yes, you can fully display and hide the keyboard and intercept calls to the back button. This is a bit of an extra effort since it was mentioned that there is no direct way to do this in the API. The key is to override boolean dispatchKeyEventPreIme(KeyEvent) in the layout. We create our layout. I chose RelativeLayout because it was the base of my activity.

 <?xml version="1.0" encoding="utf-8"?> <com.michaelhradek.superapp.utilities.SearchLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res/com.michaelhradek.superapp" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@color/white"> 

Inside our business, we customize our input fields and call the setActivity(...) function.

 private void initInputField() { mInputField = (EditText) findViewById(R.id.searchInput); InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY); mInputField.setOnEditorActionListener(new OnEditorActionListener() { @Override public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEARCH) { performSearch(); return true; } return false; } }); // Let the layout know we are going to be overriding the back button SearchLayout.setSearchActivity(this); } 

Obviously, the initInputField() function sets the input field. It also allows input keys to perform functionality (in my case, searching).

 @Override public void onBackPressed() { // It expensive, if running turn it off. DataHelper.cancelSearch(); hideKeyboard(); super.onBackPressed(); } 

So, when onBackPressed() is called inside our layout, we can do whatever we want to hide the keyboard:

 private void hideKeyboard() { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mInputField.getWindowToken(), 0); } 

Anyway, this is my redefinition of RelativeLayout.

 package com.michaelhradek.superapp.utilities; import android.app.Activity; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.KeyEvent; import android.widget.RelativeLayout; /** * The root element in the search bar layout. This is a custom view just to * override the handling of the back button. * */ public class SearchLayout extends RelativeLayout { private static final String TAG = "SearchLayout"; private static Activity mSearchActivity;; public SearchLayout(Context context, AttributeSet attrs) { super(context, attrs); } public SearchLayout(Context context) { super(context); } public static void setSearchActivity(Activity searchActivity) { mSearchActivity = searchActivity; } /** * Overrides the handling of the back key to move back to the * previous sources or dismiss the search dialog, instead of * dismissing the input method. */ @Override public boolean dispatchKeyEventPreIme(KeyEvent event) { Log.d(TAG, "dispatchKeyEventPreIme(" + event + ")"); if (mSearchActivity != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK) { KeyEvent.DispatcherState state = getKeyDispatcherState(); if (state != null) { if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) { state.startTracking(event, this); return true; } else if (event.getAction() == KeyEvent.ACTION_UP && !event.isCanceled() && state.isTracking(event)) { mSearchActivity.onBackPressed(); return true; } } } return super.dispatchKeyEventPreIme(event); } } 

Unfortunately, I can’t get a loan. If you check the source , you will see where the idea came from.

+67
Apr 27 '11 at 22:57
source share

onKeyDown () and onBackPressed () does not work for this case. You must use onKeyPreIme .

Initially, you need to create your own editing text that extends EditText. And then you have to implement the onKeyPreIme method, which controls KeyEvent.KEYCODE_BACK . After that, one back is enough to solve your problem. This solution works fine for me.

CustomEditText.java

 public class CustomEditText extends EditText { Context context; public CustomEditText(Context context, AttributeSet attrs) { super(context, attrs); this.context = context; } @Override public boolean onKeyPreIme(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { // User has pressed Back key. So hide the keyboard InputMethodManager mgr = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); mgr.hideSoftInputFromWindow(this.getWindowToken(), 0); // TODO: Hide your view as you do it in your activity } return false; } 

In your xml

 <com.YOURAPP.CustomEditText android:id="@+id/CEditText" android:layout_height="wrap_content" android:layout_width="match_parent"/> 

In your activity

 public class MainActivity extends Activity { private CustomEditText editText; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); editText = (CustomEditText) findViewById(R.id.CEditText); } } 
+50
Feb 25 '15 at 12:46
source share

I found out that overriding the dispatchKeyEventPreIme method of the Layout class also works well. Just set the main activity as an attribute and run the predefined method.

 public class LinearLayoutGradient extends LinearLayout { MainActivity a; public void setMainActivity(MainActivity a) { this.a = a; } @Override public boolean dispatchKeyEventPreIme(KeyEvent event) { if (a != null) { InputMethodManager imm = (InputMethodManager) a .getSystemService(Context.INPUT_METHOD_SERVICE); if (imm.isActive() && event.getKeyCode() == KeyEvent.KEYCODE_BACK) { a.launchMethod; } } return super.dispatchKeyEventPreIme(event); } } 
+9
Jun 05 '11 at 18:14
source share

I had success by overriding dispatchKeyEvent :

 @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { finish(); return true; } return super.dispatchKeyEvent(event); } 

He hides the keyboard and shuts down.

+7
Feb 24 2018-12-12T00:
source share

How do you show the soft keyboard?

If you use InputMethodManager.showSoftInput() , you can try ResultReceiver into ResultReceiver and implementing onReceiveResult() to handle RESULT_HIDDEN

http://developer.android.com/reference/android/view/inputmethod/InputMethodManager.html

+4
Oct. 15 '10 at 7:16
source share

I had the same problem, but get around it by intercepting a keystroke. In my case (HTC Desire, Android 2.2, Application API Level 4) it closes the keyboard and immediately terminates the Activity. Not sure why this should not work for you either:

 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { return true; } return super.onKeyDown(keyCode, event); } @Override public boolean onKeyUp(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { onBackPressed(); return true; } return super.onKeyUp(keyCode, event); } /** * Called when the activity has detected the user press of the back key */ private void onBackPressed() { Log.e(TAG, "back pressed"); finish(); } 
+2
Mar 03 '11 at 11:01
source share

Use the onKeyPreIme(int keyCode, KeyEvent event) method onKeyPreIme(int keyCode, KeyEvent event) and check the KeyEvent.KEYCODE_BACK event. It is very simple, without any fancy encodings.

+1
Nov 21 '11 at 16:09
source share

Try using this code in your BackPressed implementation ( Lock button in an Android browser ):

 InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0); 

I suggest you look @ Close / hide Android soft keyboard

0
Oct 22 '10 at 6:40
source share



All Articles