Да, есть возможность отображать и скрывать клавиатуру и перехватывать вызовы на кнопку возврата. Это требует дополнительных усилий, поскольку, как уже упоминалось, прямого способа сделать это в 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;
}
});
SearchLayout.setSearchActivity(this);
}
Очевидно, initInputField()
функция настраивает поле ввода. Он также позволяет клавише ввода выполнять функции (в моем случае поиск).
@Override
public void onBackPressed() {
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;
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;
}
@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, вы увидите, откуда пришла идея.
getContext()
кActivity
. Разумеется, при условии, что контекст макета является рассматриваемым действием. Но я не знаю, могло ли это быть.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); } }
источник
<?xml version="1.0" encoding="utf-8"?> <view class="package.LinearLayoutGradient"...
Мне удалось переопределить 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
источник
showSoftInput()
на моем телефоне и в эмуляторе не отображается клавиатура, поэтому я используюtoggleSoftInput()
У меня была та же проблема, но я обошел ее, перехватив нажатие клавиши возврата. В моем случае (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
событие. Это очень просто, без сложного кодирования.источник
Попробуйте этот код в своей реализации BackPressed ( кнопка блокировки возврата в android ):
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(myEditText.getWindowToken(), 0);
Предлагаю вам взглянуть на @ Close / Hide the Android Soft Keyboard
источник
onBackPressed()
не работает. И только после второго пресса программа попадает вonBackPressed()
.моя версия решения @mhradek:
Макет
class BazingaLayout @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : ConstraintLayout(context, attrs, defStyleAttr) { var activity: Activity? = null override fun dispatchKeyEventPreIme(event: KeyEvent): Boolean { activity?.let { if (event.keyCode == KeyEvent.KEYCODE_BACK) { val state = keyDispatcherState if (state != null) { if (event.action == KeyEvent.ACTION_DOWN && event.repeatCount == 0) { state.startTracking(event, this) return true } else if (event.action == KeyEvent.ACTION_UP && !event.isCanceled && state.isTracking(event)) { it.onBackPressed() return true } } } } return super.dispatchKeyEventPreIme(event) }
}
xml файл
<com... BazingaLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/grey"> </com... BazingaLayout>
Фрагмент
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { (view as BazingaLayout).activity = activity super.onViewCreated(view, savedInstanceState) }
источник