Android : Handle back button click when keyboard is open for EditText
I did few modifications to @GuanHongHuang's answer and now I am able to do this by these 3 steps:
1. Creating Custom EditText Class to handle Back Press:
public class CustomEditTextWithBackPressEvent extends androidx.appcompat.widget.AppCompatEditText {
private MyEditTextListener onBackPressListener;
public CustomEditTextWithBackPressEvent(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setOnBackPressListener(MyEditTextListener onBackPressListener) {
this.onBackPressListener = onBackPressListener;
}
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK &&
event.getAction() == KeyEvent.ACTION_UP) {
//back button pressed
if (Objects.requireNonNull(ViewCompat.getRootWindowInsets(getRootView())).isVisible(WindowInsetsCompat.Type.ime())) {
//keyboard is open
onBackPressListener.callback();
}
return false;
}
return super.dispatchKeyEvent(event);
}
public interface MyEditTextListener {
void callback();
}
}
2. Replace your normal EditText with this CustomEditTextWithBackPressEvent in XML
<CustomEditTextWithBackPressEvent
android:id="@+id/etSearch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/search_hint"
android:imeOptions="actionSearch"
android:inputType="text"
android:maxLines="1" />
3. Handle Back Press:
binding.etSearch.setOnBackPressListener(() -> {
//handle click
//your code here
});
EditText with soft keyboard and Back button
You can override when the keyboard disappears using this method:
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK &&
event.getAction() == KeyEvent.ACTION_UP) {
// Do your thing here
return false;
}
return super.dispatchKeyEvent(event);
}
Taken from my other answer @ : Android: Error popup on EditText doesn't move down when keyboard goes away
Intercept back button from soft keyboard
Yes, it is completely possible to show and hide the keyboard and intercept the calls to the back button. It is a little extra effort as it has been mentioned there is no direct way to do this in the API. The key is to override boolean dispatchKeyEventPreIme(KeyEvent)
within a layout. What we do is create our layout. I chose RelativeLayout since 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 Activity we set up 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 up the input field. It also enables the enter key to execute the functionality (in my case a search).
@Override
public void onBackPressed() {
// It's expensive, if running turn it off.
DataHelper.cancelSearch();
hideKeyboard();
super.onBackPressed();
}
So when the onBackPressed()
is called within our layout we then can do whatever we want like hide the keyboard:
private void hideKeyboard() {
InputMethodManager imm = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mInputField.getWindowToken(), 0);
}
Anyway, here is my override of the 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 take all the credit. If you check the Android source for the quick SearchDialog box you will see where the idea came from.
How do I make an Android EditView 'Done' button and hide the keyboard when clicked?
Use TextView.setImeOptions and pass it actionDone.
like textView.setImeOptions(EditorInfo.IME_ACTION_DONE);
one back-button click lowers a soft-keyboard and exits activity at the same time
Just override activity method and finish explicitly
@Override
public void onBackPressed() {
finish();
}
UPDATED2
Yes, this doesn't work for such case. But I've tried few solutions and one of them did work. You need to extend EditText and override method:
@Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
((Activity)getContext()).finish();
return true;
}
return super.onKeyPreIme(keyCode, event);
}
Note:
don't forget to replace your previous EditText
in layout xml with new extented class
Related Topics
How to Handle System_Alert_Window Permission Not Being Auto-Granted on Some Pre-Marshmallow Devices
How to Release Application Plugin Using Android Market
Errors Managing the Unityplayer Lifecycle in a Native Android Application
Android Cardview Remove Padding
Push Up Content When Clicking in Edit Text
How to Use Data Binding and Kotlin in Android Studio 3.0.0
Status Bar Turns White and Does Not Show Content Behind It
Rendering Problems in Android Studio V 1.1/1.2
How to Open Navigation Drawer with No Actionbar, Open with Just a Button
Android 5.0: How to Change Recent Apps Title Color
Proguard Warnings "Can't Write Resource [Meta-Inf/Manifest.Mf] (Duplicate Zip Entry)"
Tablayout Tab Title Text in Lower Case
Difference Between Addvalueeventlistener() and Addlistenerforsinglevalueevent() of Firebase
Chaining Requests in Retrofit + Rxjava
Android - Use External Profile Image in Notification Bar Like Facebook
After Update of as to 1.0, Getting "Method Id Not in [0, 0Xffff]: 65536" Error in Project