Intercept Back Button from Soft Keyboard

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 to intercept flutter back-button when keyboard is shown

you can use the keyboard_visibility package to achieve this.

Working Example

the following code displays a SnackBar once the keyboard is dismissed.

import 'package:flutter/material.dart';
import 'package:keyboard_visibility/keyboard_visibility.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
GlobalKey<ScaffoldState> _key;

@override
void initState() {
super.initState();
_key = GlobalKey<ScaffoldState>();
KeyboardVisibilityNotification().addNewListener(
onHide: () {
_key.currentState.showSnackBar(
SnackBar(
content: Text("Keyboard closed"),
),
);
},
);
}

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _key,
body: Center(
child: TextField(),
),
),
);
}
}

Android Sample Image 17

Android - onBackPressed close soft keyboard AND activity

You can create customized view and implement onKeyPreIme(keyCode: Int, event: KeyEvent) and check for keyCode == KeyEvent.KEYCODE_BACK event.

Hope this answer will explain it to you furthermore.

Edited:

try to implement these for your SearchView:

searchInput.setOnQueryTextFocusChangeListener{ _, b->
if(!b){
searchview.isIconified = true
finish()
}
}

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

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
});


Related Topics



Leave a reply



Submit