每个人都知道要隐藏一个键盘,你需要实现:
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
但这里的大问题是如何隐藏键盘时,用户触摸或选择任何其他地方,不是一个EditText或softKeyboard?
我尝试在我的父活动上使用onTouchEvent(),但只有当用户在任何其他视图之外触摸并且没有滚动视图时才有效。
我试图实现一个触摸,点击,焦点监听器,但没有任何成功。
我甚至尝试实现我自己的滚动视图来拦截触摸事件,但我只能得到事件的坐标,而不是视图被单击。
有标准的方法来做这件事吗?在iPhone中,这非常简单。
只需在活动中覆盖下面的代码
@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)
}
我已经改进了方法,把下面的代码放在一些UI实用工具类(最好,不一定),这样它可以从所有的活动或片段类访问,以达到它的目的。
public static void serachAndHideSoftKeybordFromView(View view, final Activity act) {
if(!(view instanceof EditText)) {
view.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
hideSoftKeyboard(act);
return false;
}
});
}
if (view instanceof ViewGroup) {
for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
View nextViewInHierarchy = ((ViewGroup) view).getChildAt(i);
serachAndHideSoftKeybordFromView(nextViewInHierarchy, act);
}
}
}
public static void hideSoftKeyboard (Activity activity) {
InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0);
}
然后假设你需要从activity中调用它,像这样调用;
UIutils.serachAndHideSoftKeybordFromView(findViewById(android.R.id.content), YourActivityName.this);
请注意
findViewById (android.R.id.content)
这给了我们当前组的根视图(你不能在根视图上设置id)。
欢呼:)
你可以通过以下步骤来实现这一点:
Make the parent view(content view of your activity) clickable and focusable by adding the following attributes
android:clickable="true"
android:focusableInTouchMode="true"
Implement a hideKeyboard() method
public void hideKeyboard(View view) {
InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
Lastly, set the onFocusChangeListener of your edittext.
edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
hideKeyboard(v);
}
}
});
正如下面的一条评论所指出的,如果父视图是ScrollView,这可能不起作用。对于这种情况,clickable和focusableInTouchMode可以直接添加到ScrollView下面的视图上。
好吧,我设法某种程度上解决了这个问题,我在我的活动上覆盖了dispatchTouchEvent,在那里我使用下面的隐藏键盘。
/**
* Called to process touch screen events.
*/
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_DOWN:
touchDownTime = SystemClock.elapsedRealtime();
break;
case MotionEvent.ACTION_UP:
//to avoid drag events
if (SystemClock.elapsedRealtime() - touchDownTime <= 150){
EditText[] textFields = this.getFields();
if(textFields != null && textFields.length > 0){
boolean clickIsOutsideEditTexts = true;
for(EditText field : textFields){
if(isPointInsideView(ev.getRawX(), ev.getRawY(), field)){
clickIsOutsideEditTexts = false;
break;
}
}
if(clickIsOutsideEditTexts){
this.hideSoftKeyboard();
}
} else {
this.hideSoftKeyboard();
}
}
break;
}
return super.dispatchTouchEvent(ev);
}
编辑:getFields()方法只是一个在视图中返回带有文本字段的数组的方法。为了避免每次触摸都创建这个数组,我创建了一个名为sFields的静态数组,它在getFields()方法中返回。该数组在onStart()方法上初始化,例如:
《新经》[英文]
它不是完美的,拖动事件时间只是基于启发式,所以有时它不会隐藏在执行长clics时,我也完成了创建一个方法来获得每个视图的所有editTexts;否则,当单击其他EditText时,键盘将隐藏和显示。
不过,更干净、更短的解决方案还是受欢迎的