拦截软键盘上的button

我有几个input字段的活动。 当活动开始软键盘显示。 当后退button按下软键盘closures并closures活动,我需要再按一次button。

所以问题是:是否有可能拦截返回buttonclosures软键盘,并完成一个按下后退button的活动,而不创build自定义的InputMethodService

PS我知道如何在其他情况下拦截返回button: onKeyDown()onBackPressed()但在这种情况下不起作用:只有第二次按下后退button被拦截。

是的,完全可以显示和隐藏键盘并拦截对后退button的呼叫。 这是一个额外的努力,因为它已经被提到没有直接的方式来做到这一点在API中。 关键是重写布局中的boolean dispatchKeyEventPreIme(KeyEvent) 。 我们所做的是创build我们的布局。 我select了RelativeLayout,因为它是我的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"> 

在我们的Activity中,我们设置了input字段并调用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()函数设置input字段。 它也使input键执行function(在我的情况下search)。

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

不幸的是,我不能把所有的信用。 如果您检查快速SearchDialog框的Android 源代码,您将看到这个想法来自哪里。

onKeyDown()onBackPressed()不适用于这种情况。 你必须使用onKeyPreIme

最初,您必须创build扩展EditText的自定义编辑文本。 然后你必须实现控制KeyEvent.KEYCODE_BACK的 onKeyPreIme方法。 在此之后,一个回足够解决你的问题。 这个解决scheme对我来说完美。

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

在你的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方法也很好。 只需将您的主要活动设置为属性并启动预定义的方法即可。

 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,应用程序API级别4),它closures键盘,并立即完成活动。 不知道为什么这也不适合你:

 @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中禁止返回button ):

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

我build议你看看@ closures/隐藏Android软键盘