每个人都知道要隐藏一个键盘,你需要实现:
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
但这里的大问题是如何隐藏键盘时,用户触摸或选择任何其他地方,不是一个EditText或softKeyboard?
我尝试在我的父活动上使用onTouchEvent(),但只有当用户在任何其他视图之外触摸并且没有滚动视图时才有效。
我试图实现一个触摸,点击,焦点监听器,但没有任何成功。
我甚至尝试实现我自己的滚动视图来拦截触摸事件,但我只能得到事件的坐标,而不是视图被单击。
有标准的方法来做这件事吗?在iPhone中,这非常简单。
我喜欢调用dispatchTouchEvent的方法由htafoya,但是:
我不理解定时器的部分(不知道为什么测量停机时间应该是必要的?)
我不喜欢注册/取消注册所有的EditTexts与每一个视图的变化(可能是相当多的视图变化和编辑文本在复杂的层次结构)
所以,我做了一个更简单的解决方案:
@Override
public boolean dispatchTouchEvent(final MotionEvent ev) {
// all touch events close the keyboard before they are processed except EditText instances.
// if focus is an EditText we need to check, if the touchevent was inside the focus editTexts
final View currentFocus = getCurrentFocus();
if (!(currentFocus instanceof EditText) || !isTouchInsideView(ev, currentFocus)) {
((InputMethodManager) getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE))
.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
}
return super.dispatchTouchEvent(ev);
}
/**
* determine if the given motionevent is inside the given view.
*
* @param ev
* the given view
* @param currentFocus
* the motion event.
* @return if the given motionevent is inside the given view
*/
private boolean isTouchInsideView(final MotionEvent ev, final View currentFocus) {
final int[] loc = new int[2];
currentFocus.getLocationOnScreen(loc);
return ev.getRawX() > loc[0] && ev.getRawY() > loc[1] && ev.getRawX() < (loc[0] + currentFocus.getWidth())
&& ev.getRawY() < (loc[1] + currentFocus.getHeight());
}
但有一个缺点:
从一个EditText切换到另一个EditText使键盘隐藏并重新显示——在我的例子中,这是理想的方式,因为它显示您在两个输入组件之间切换。
活动
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
ScreenUtils.hideKeyboard(this, findViewById(android.R.id.content).getWindowToken());
return super.dispatchTouchEvent(ev);
}
ScreenUtils
public static void hideKeyboard(Context context, IBinder windowToken) {
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS);
}
我设法隐藏键盘从onItemClick AutoCompleteTextView
public void onItemClick(AdapterView<?> adapterViewIn, View viewIn, int indexSelected, long arg3) {
InputMethodManager imm = (InputMethodManager) getSystemService(viewIn.getContext().INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(viewIn.getApplicationWindowToken(), 0);
// your code HERE
}
你可以试试下面的方法,它对我很有用:)
这种方式可以应用于活动或片段,它也与ScrollView兼容。
我们将ScrollView作为顶级布局,在LinearLayout中声明id parentView,并添加如下两个属性:
android:id="@+id/parentView"
android:clickable="true"
android:focusableInTouchMode="true"
在代码中,编写如下函数:
public static void hideSoftKeyboard (Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
然后为根视图注册一个OnFocusChangeListener(写入onCreate方法),使Activity中的所有EditText受到影响:
parentLayout.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
hideSoftKeyboard(your_activity_name.this);
}
}
});
只需在活动中覆盖下面的代码
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (getCurrentFocus() != null) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
}
return super.dispatchTouchEvent(ev);
}
更新:
如果有人需要这个答案的Kotlin版本:
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
if (currentFocus != null) {
val imm = activity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(activity!!.currentFocus!!.windowToken, 0)
}
return super.dispatchTouchEvent(ev)
}