Кнопка перехвата назад с мягкой клавиатуры
у меня есть активность с несколькими полями ввода. При запуске активности отображается программная клавиатура. Когда кнопка "Назад" нажата, мягкая клавиатура закрывается, и чтобы закрыть активность, мне нужно еще раз нажать кнопку "Назад".
Итак, вопрос: Можно ли перехватить кнопку "назад", чтобы закрыть мягкую клавиатуру и закончить работу одним нажатием кнопки "назад" без создания пользовательского InputMethodService
?
P. S. Я знаю как перехватить кнопку обратно в других случаях: onKeyDown()
или onBackPressed()
но это не работает в этом случае: перехватывается только второе нажатие кнопки "Назад".
8 ответов:
да, вполне возможно показать и спрятать клавиатуру и перехватить звоноки к задней кнопке. Это немного дополнительные усилия, как уже упоминалось, нет прямого способа сделать это в API. Ключ должен переопределить
boolean dispatchKeyEventPreIme(KeyEvent)
в макете. То, что мы делаем, это создать наш макет. Я выбрал RelativeLayout, так как это было основой моей деятельности.<?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">
внутри нашей деятельности мы настраиваем наши поля ввода и вызываем
setActivity(...)
функция.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); }
очевидно, что
initInputField()
функция устанавливает поле ввода. Он также позволяет ввести ключ для выполнения функции (в моем случае поиск).@Override public void onBackPressed() { // It's expensive, if running turn it off. DataHelper.cancelSearch(); hideKeyboard(); super.onBackPressed(); }
когда
onBackPressed()
называется в нашем макете мы тогда можем делать все, что мы хотим, как скрыть клавиатуру:private void hideKeyboard() { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mInputField.getWindowToken(), 0); }
в любом случае, вот мое переопределение 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); } }
к сожалению, я не могу взять на себя всю ответственность. Если вы проверите Android источник для быстрого SearchDialog box вы увидите, откуда пришла идея.
onKeyDown () и onBackPressed() не работает в этом случае. Вы должны использовать onKeyPreIme.
первоначально, вы должны создать пользовательский текст редактирования, который расширяет EditText. И тогда вы должны реализовать onKeyPreIme метод, который управляет KeyEvent.KEYCODE_BACK. После этого достаточно одного нажатия назад, чтобы решить вашу проблему. Это решение работает для меня отлично.
CustomEditText.java
public class CustomEditText extends EditText { public CustomEditText(Context context, AttributeSet attrs) { super(context, attrs); } @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) getContext().getSystemService(Context.INPUT_METHOD_SERVICE); mgr.hideSoftInputFromWindow(this.getWindowToken(), 0); // TODO: Hide your view as you do it in your activity } return false; }
в XML
<com.YOURAPP.CustomEditText android:id="@+id/CEditText" android:layout_height="wrap_content" android:layout_width="match_parent"/>
в работе
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); } }
я узнал, что переопределение dispatchKeyEventPreIme метод класса Layout также работает хорошо. Просто установите свой основной вид деятельности в качестве атрибута и запустите предопределенный метод.
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); } }
Я имел успех, переопределив dispatchKeyEvent:
@Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) { finish(); return true; } return super.dispatchKeyEvent(event); }
он скрывает клавиатуру и завершает работу.
как вы показываете мягкую клавиатуру?
если вы используете
InputMethodManager.showSoftInput()
, вы можете попробовать пройти вResultReceiver
и осуществляетonReceiveResult()
обработкиRESULT_HIDDEN
http://developer.android.com/reference/android/view/inputmethod/InputMethodManager.html
У меня была та же проблема, но я обошел ее, перехватывая нажатие клавиши Назад. В моем случае (HTC Desire, Android 2.2, Application API Level 4) он закрывает клавиатуру и сразу же заканчивает работу. Не знаю, почему это не должно работать для вас:
@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's press of the back key */ private void onBackPressed() { Log.e(TAG, "back pressed"); finish(); }
использовать
onKeyPreIme(int keyCode, KeyEvent event)
метод и проверка наKeyEvent.KEYCODE_BACK
событие. Это очень просто, не делая каких-либо фантазии кодирования.
попробуйте этот код в вашей обратной реализации ( кнопка блокировки назад в android):
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);
Я предлагаю вам посмотреть @ закрыть / скрыть программную клавиатуру Android