How to hide soft keyboard on android after clicking outside EditText?
好的,大家都知道要隐藏你需要实现的键盘:
1 2 | InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); |
但这里最重要的是当用户触摸或选择不是
我试图在我的父
我尝试实现触摸,单击,集中监听器而没有任何成功。
我甚至尝试实现自己的scrollview来拦截触摸事件,但我只能获取事件的坐标而不是点击的视图。
有没有一种标准的方法来做到这一点? 在iPhone中它真的很容易。
以下代码段只是隐藏了键盘:
1 2 3 4 5 6 7 | public static void hideSoftKeyboard(Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService( Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow( activity.getCurrentFocus().getWindowToken(), 0); } |
您可以将其放在实用程序类中,或者如果要在活动中定义它,请避免使用activity参数,或调用
最棘手的部分是何时调用它。您可以编写一个循环遍历活动中每个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public void setupUI(View view) { // Set up touch listener for non-text box views to hide keyboard. if (!(view instanceof EditText)) { view.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { hideSoftKeyboard(MyActivity.this); return false; } }); } //If a layout container, iterate over children and seed recursion. if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { View innerView = ((ViewGroup) view).getChildAt(i); setupUI(innerView); } } } |
就是这样,只需在活动中
并调用
如果要有效地使用它,可以创建扩展
希望能帮助到你。
如果您使用多个活动,则将父公布定义为公共ID
然后从
您可以通过执行以下步骤来实现此目的:
通过添加以下属性,使父视图(活动的内容视图)可单击并可聚焦
1 2 | android:clickable="true" android:focusableInTouchMode="true" |
实现hideKeyboard()方法
1 2 3 4 | public void hideKeyboard(View view) { InputMethodManager inputMethodManager =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); } |
最后,设置edittext的onFocusChangeListener。
1 2 3 4 5 6 7 8 | edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { hideKeyboard(v); } } }); |
正如下面的一条评论中所指出的,如果父视图是ScrollView,这可能不起作用。对于这种情况,可以在ScrollView正下方的视图上添加clickable和focusableInTouchMode。
我发现接受的答案有点复杂。
这是我的解决方案。在主布局中添加
1 | findViewById(R.id.mainLayout).setOnTouchListener(this) |
并将以下代码放在onTouch方法中。
1 2 | InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); |
这样您就不必遍历所有视图。
我还有一个解决方案来隐藏键盘:
1 2 3 | InputMethodManager imm = (InputMethodManager) getSystemService( Activity.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); |
这里
它将强制关闭软键盘。
只需覆盖Activity中的以下代码即可
1 2 3 4 5 6 7 8 | @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); } |
好吧我设法解决了这个问题,我在我的活动上覆盖了dispatchTouchEvent,在那里我使用以下来隐藏键盘。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | /** * 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()方法上初始化,例如:
它并不完美,拖动事件时间只是基于启发式,所以有时它在执行长文件时不会隐藏,我还完成了创建一个方法来获取每个视图的所有editTexts;否则键盘会在单击其他EditText时隐藏和显示。
仍然,欢迎更清洁和更短的解决方案
使用OnFocusChangeListener。
例如:
1 2 3 4 5 6 7 8 | editText.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { hideKeyboard(); } } }); |
更新:您还可以覆盖活动中的
我在Activity中实现了dispatchTouchEvent来执行此操作:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | private EditText mEditText; private Rect mRect = new Rect(); @Override public boolean dispatchTouchEvent(MotionEvent ev) { final int action = MotionEventCompat.getActionMasked(ev); int[] location = new int[2]; mEditText.getLocationOnScreen(location); mRect.left = location[0]; mRect.top = location[1]; mRect.right = location[0] + mEditText.getWidth(); mRect.bottom = location[1] + mEditText.getHeight(); int x = (int) ev.getX(); int y = (int) ev.getY(); if (action == MotionEvent.ACTION_DOWN && !mRect.contains(x, y)) { InputMethodManager input = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); input.hideSoftInputFromWindow(mEditText.getWindowToken(), 0); } return super.dispatchTouchEvent(ev); } |
我测试了它,效果很好!
在任何Activity中覆盖公共布尔dispatchTouchEvent(MotionEvent事件)(或扩展Activity类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Override public boolean dispatchTouchEvent(MotionEvent event) { View view = getCurrentFocus(); boolean ret = super.dispatchTouchEvent(event); if (view instanceof EditText) { View w = getCurrentFocus(); int scrcoords[] = new int[2]; w.getLocationOnScreen(scrcoords); float x = event.getRawX() + w.getLeft() - scrcoords[0]; float y = event.getRawY() + w.getTop() - scrcoords[1]; if (event.getAction() == MotionEvent.ACTION_UP && (x < w.getLeft() || x >= w.getRight() || y < w.getTop() || y > w.getBottom()) ) { InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getWindow().getCurrentFocus().getWindowToken(), 0); } } return ret; } |
这就是你需要做的一切
更多Kotlin&amp;使用TextInputEditText的Material Design方式(这种方法也与EditTextView兼容)......
1.通过添加以下属性,使父视图(活动/片段的内容视图)可单击并可聚焦
1 2 3 | android:focusable="true" android:focusableInTouchMode="true" android:clickable="true" |
2.为所有View创建扩展(例如,在ViewExtension.kt文件中):
1 2 3 4 | fun View.hideKeyboard(){ val inputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager inputMethodManager.hideSoftInputFromWindow(this.windowToken, 0) } |
3.创建继承TextInputEditText的BaseTextInputEditText。在视图未聚焦时,实现onFocusChanged方法隐藏键盘:
1 2 3 4 5 6 | class BaseTextInputEditText(context: Context?, attrs: AttributeSet?) : TextInputEditText(context, attrs){ override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) { super.onFocusChanged(focused, direction, previouslyFocusedRect) if (!focused) this.hideKeyboard() } } |
4.只需在XML中调用全新的自定义视图:
1 2 3 4 5 6 7 8 9 10 | <android.support.design.widget.TextInputLayout android:id="@+id/textInputLayout" ...> <com.your_package.BaseTextInputEditText android:layout_width="match_parent" android:layout_height="wrap_content" ... /> </android.support.design.widget.TextInputLayout> |
就这样。无需修改控制器(片段或活动)来处理这种重复的情况。
我知道这个线程已经很老了,正确的答案似乎是有效的,并且有很多工作解决方案,但我认为下面提出的方法可能会在效率和优雅方面带来额外的好处。
我的所有活动都需要这种行为,所以我创建了一个继承自Activity类的CustomActivity类,并"挂钩"了dispatchTouchEvent函数。主要有两个条件需要照顾:
这是我的结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | @Override public boolean dispatchTouchEvent(MotionEvent ev) { if(ev.getAction() == MotionEvent.ACTION_UP) { final View view = getCurrentFocus(); if(view != null) { final boolean consumed = super.dispatchTouchEvent(ev); final View viewTmp = getCurrentFocus(); final View viewNew = viewTmp != null ? viewTmp : view; if(viewNew.equals(view)) { final Rect rect = new Rect(); final int[] coordinates = new int[2]; view.getLocationOnScreen(coordinates); rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight()); final int x = (int) ev.getX(); final int y = (int) ev.getY(); if(rect.contains(x, y)) { return consumed; } } else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) { return consumed; } final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0); viewNew.clearFocus(); return consumed; } } return super.dispatchTouchEvent(ev); } |
旁注:此外,我将这些属性分配给根视图,从而可以清除对每个输入字段的关注,并防止输入字段聚焦于活动启动(使内容视图成为"焦点捕获器"):
1 2 3 4 5 6 7 8 9 | @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final View view = findViewById(R.id.content); view.setFocusable(true); view.setFocusableInTouchMode(true); } |
我修改了Andre Luis IM的解决方案我实现了这个:
我创建了一个实用工具方法来隐藏软键盘,就像Andre Luiz IM所做的那样:
1 2 3 4 | public static void hideSoftKeyboard(Activity activity) { InputMethodManager inputMethodManager = (InputMethodManager) activity.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(activity.getCurrentFocus().getWindowToken(), 0); } |
但是,不是为每个视图注册一个OnTouchListener,而是性能很差,我只为root视图注册了OnTouchListener。由于事件一直消耗直到被消耗(EditText是默认使用它的视图之一),如果它到达根视图,那是因为它没有被消耗,所以我关闭了软键盘。
1 2 3 4 5 6 7 | findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Utils.hideSoftKeyboard(activity); return false; } }); |
我喜欢调用htafoya制作的
- 我不明白计时器部分(不知道为什么要测量停机时间?)
- 我不喜欢在每次视图更改时注册/取消注册所有EditTexts(在复杂的层次结构中可能有很多视图更改和edittexts)
所以,我做了一些更简单的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | @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()); } |
有一个缺点:
从一个
辩诉:我知道我没有影响力,但请认真对待我的回答。
问题:单击远离键盘或使用最少代码编辑文本时,关闭软键盘。
解决方案:外部库称为Butterknife。
单线解决方案:
1 | @OnClick(R.id.activity_signup_layout) public void closeKeyboard() { ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } |
更易读的解决方案:
1 2 3 4 5 | @OnClick(R.id.activity_signup_layout) public void closeKeyboard() { InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } |
说明:将OnClick侦听器绑定到活动的XML布局父ID,以便对布局(而不是编辑文本或键盘)上的任何单击都将运行将隐藏键盘的代码片段。
示例:如果您的布局文件是R.layout.my_layout,并且您的布局ID是R.id.my_layout_id,那么您的Butterknife绑定调用应该如下所示:
1 2 3 4 5 | (@OnClick(R.id.my_layout_id) public void yourMethod { InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } |
Butterknife文档链接:http://jakewharton.github.io/butterknife/
插件:Butterknife将彻底改变您的Android开发。考虑一下。
注意:如果不使用外部库Butterknife,可以获得相同的结果。只需将OnClickListener设置为父布局,如上所述。
这是fje的答案的另一个变体,它解决了sosite提出的问题。
这里的想法是处理Activity的
在up动作中,我们首先发送,以允许另一个视图可能成为焦点。如果在此之后,当前聚焦的视图是最初聚焦的视图,并且向下触摸在该视图内,则我们使键盘保持打开状态。
如果当前聚焦的视图与最初聚焦的视图不同并且它是
否则我们关闭它。
总而言之,这可以如下工作:
-
当触摸当前聚焦的
EditText 内部时,键盘保持打开状态 -
当从焦点
EditText 移动到另一个EditText 时,键盘保持打开状态(不关闭/重新打开) -
当触摸当前聚焦的
EditText (不是另一个EditText )之外的任何地方时,键盘关闭 -
当长按
EditText 以调出上下文操作栏(使用剪切/复制/粘贴按钮)时,键盘保持打开状态,即使UP操作发生在聚焦EditText 之外(向下移动到为CAB腾出空间)。但请注意,当您点击CAB中的按钮时,它将关闭键盘。这可能是也可能不是可取的;如果你想从一个字段剪切/复制并粘贴到另一个字段,那就是。如果要粘贴回相同的EditText ,则不会。 -
当焦点
EditText 位于屏幕底部并且您长按某些文本以选择它时,EditText 保持焦点,因此键盘会按照您的需要打开,因为我们执行"触摸在视图范围内""检查下行动,而不是上行动。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60private View focusedViewOnActionDown;
private boolean touchWasInsideFocusedView;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
focusedViewOnActionDown = getCurrentFocus();
if (focusedViewOnActionDown != null) {
final Rect rect = new Rect();
final int[] coordinates = new int[2];
focusedViewOnActionDown.getLocationOnScreen(coordinates);
rect.set(coordinates[0], coordinates[1],
coordinates[0] + focusedViewOnActionDown.getWidth(),
coordinates[1] + focusedViewOnActionDown.getHeight());
final int x = (int) ev.getX();
final int y = (int) ev.getY();
touchWasInsideFocusedView = rect.contains(x, y);
}
break;
case MotionEvent.ACTION_UP:
if (focusedViewOnActionDown != null) {
// dispatch to allow new view to (potentially) take focus
final boolean consumed = super.dispatchTouchEvent(ev);
final View currentFocus = getCurrentFocus();
// if the focus is still on the original view and the touch was inside that view,
// leave the keyboard open. Otherwise, if the focus is now on another view and that view
// is an EditText, also leave the keyboard open.
if (currentFocus.equals(focusedViewOnActionDown)) {
if (touchWasInsideFocusedView) {
return consumed;
}
} else if (currentFocus instanceof EditText) {
return consumed;
}
// the touch was outside the originally focused view and not inside another EditText,
// so close the keyboard
InputMethodManager inputMethodManager =
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(
focusedViewOnActionDown.getWindowToken(), 0);
focusedViewOnActionDown.clearFocus();
return consumed;
}
break;
}
return super.dispatchTouchEvent(ev);
}
它过于简单,只需通过以下代码使您最近的布局可点击:
1 2 3 | android:id="@+id/loginParentLayout" android:clickable="true" android:focusableInTouchMode="true" |
然后为该布局编写一个方法和一个OnClickListner,这样当触摸最上面的布局时,它会调用一个方法,在这个方法中你将编写代码来解除键盘。以下是两者的代码;
//你必须在OnCreate()中写这个
1 2 3 4 5 6 | yourLayout.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View view) { hideKeyboard(view); } }); |
从listner调用的方法: -
1 2 3 4 | public void hideKeyboard(View view) { InputMethodManager imm =(InputMethodManager)getSystemService(Activity.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(view.getWindowToken(), 0); } |
对于这个简单的要求,我发现接受的答案有点复杂。这对我来说没有任何故障。
1 2 3 4 5 6 7 8 | findViewById(R.id.mainLayout).setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); return false; } }); |
显示/隐藏软键盘的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | InputMethodManager inputMethodManager = (InputMethodManager) currentActivity.getSystemService(Context.INPUT_METHOD_SERVICE); if (isShow) { if (currentActivity.getCurrentFocus() == null) { inputMethodManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0); } else { inputMethodManager.showSoftInput(currentActivity.getCurrentFocus(), InputMethodManager.SHOW_FORCED); } } else { if (currentActivity.getCurrentFocus() == null) { inputMethodManager.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0); } else { inputMethodManager.hideSoftInputFromInputMethod(currentActivity.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); } } |
我希望他们有用
我已经改进了方法,将以下代码放在一些UI实用程序类中(最好不一定),以便可以从所有Activity或Fragment类访问它以实现其目的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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); } |
然后说例如你需要从活动中调用它,如下调用它;
1 | UIutils.serachAndHideSoftKeybordFromView(findViewById(android.R.id.content), YourActivityName.this); |
注意
findViewById(android.R.id.content)
这为我们提供了当前组的根视图(您不能在根视图上设置id)。
干杯:)
有一种更简单的方法,基于iPhone同样的问题。只需覆盖触摸事件的背景布局,其中包含编辑文本。只需在活动的OnCreate中使用此代码(login_fondo是根布局):
1 2 3 4 5 6 7 8 9 10 11 12 | final LinearLayout llLogin = (LinearLayout)findViewById(R.id.login_fondo); llLogin.setOnTouchListener( new OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent ev) { InputMethodManager imm = (InputMethodManager) mActivity.getSystemService( android.content.Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(mActivity.getCurrentFocus().getWindowToken(), 0); return false; } }); |
在kotlin,我们可以做到以下几点。无需迭代所有视图。它也适用于碎片。
1 2 3 4 5 6 7 8 9 | override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { currentFocus?.let { val imm: InputMethodManager = getSystemService( Context.INPUT_METHOD_SERVICE ) as (InputMethodManager) imm.hideSoftInputFromWindow(it.windowToken, 0) } return super.dispatchTouchEvent(ev) } |
尝试将stateHidden设置为您的活动
http://developer.android.com/reference/android/R.attr.html#windowSoftInputMode
例如,对于您的活动:
1 2 | this.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); |
这是fje的答案的略微修改版本,大部分都很完美。
此版本使用ACTION_DOWN,因此执行滚动操作也会关闭键盘。
除非您单击另一个EditText,否则它也不会传播该事件。这意味着单击EditText外的任何位置,即使是另一个可单击的,也只需关闭键盘即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | @Override public boolean dispatchTouchEvent(MotionEvent ev) { if(ev.getAction() == MotionEvent.ACTION_DOWN) { final View view = getCurrentFocus(); if(view != null) { final View viewTmp = getCurrentFocus(); final View viewNew = viewTmp != null ? viewTmp : view; if(viewNew.equals(view)) { final Rect rect = new Rect(); final int[] coordinates = new int[2]; view.getLocationOnScreen(coordinates); rect.set(coordinates[0], coordinates[1], coordinates[0] + view.getWidth(), coordinates[1] + view.getHeight()); final int x = (int) ev.getX(); final int y = (int) ev.getY(); if(rect.contains(x, y)) { super.dispatchTouchEvent(ev); return true; } } else if(viewNew instanceof EditText || viewNew instanceof CustomEditText) { super.dispatchTouchEvent(ev); return true; } final InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(viewNew.getWindowToken(), 0); viewNew.clearFocus(); return true; } } return super.dispatchTouchEvent(ev); } |
1 2 3 4 5 6 7 | @Override public boolean onTouchEvent(MotionEvent event) { InputMethodManager imm = (InputMethodManager)getSystemService(Context. INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); return true; } |
只需在课程中添加此代码即可
@Overide
1 2 3 4 5 6 7 8 9 10 11 12 | public boolean dispatchTouchEvent(MotionEvent ev) { View view = getCurrentFocus(); if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) { int scrcoords[] = new int[2]; view.getLocationOnScreen(scrcoords); float x = ev.getRawX() + view.getLeft() - scrcoords[0]; float y = ev.getRawY() + view.getTop() - scrcoords[1]; if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom()) ((InputMethodManager)this.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((this.getWindow().getDecorView().getApplicationWindowToken()), 0); } return super.dispatchTouchEvent(ev); } |
我这样做了:
1 2 3 4 5 6 7 8 9 10 11 12 13 | @Override public boolean dispatchTouchEvent(MotionEvent ev) { View view = getCurrentFocus(); if (view != null && (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_MOVE) && view instanceof EditText && !view.getClass().getName().startsWith("android.webkit.")) { int scrcoords[] = new int[2]; view.getLocationOnScreen(scrcoords); float x = ev.getRawX() + view.getLeft() - scrcoords[0]; float y = ev.getRawY() + view.getTop() - scrcoords[1]; if (x < view.getLeft() || x > view.getRight() || y < view.getTop() || y > view.getBottom()) hideKeyboard(this); } return super.dispatchTouchEvent(ev); } |
隐藏键盘代码:
1 2 3 4 | public static void hideKeyboard(Activity act) { if(act!=null) ((InputMethodManager)act.getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow((act.getWindow().getDecorView().getApplicationWindowToken()), 0); } |
完成
要解决此问题,您需要首先使用该Edittext的setOnFocusChangeListener
1 2 3 4 5 6 7 8 9 10 11 | edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (!hasFocus) { Log.d("focus","focus loosed"); // Do whatever you want here } else { Log.d("focus","focused"); } } }); |
然后你需要做的是覆盖包含Edittext的活动中的dispatchTouchEvent,见下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Override public boolean dispatchTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { View v = getCurrentFocus(); if ( v instanceof EditText) { Rect outRect = new Rect(); v.getGlobalVisibleRect(outRect); if (!outRect.contains((int)event.getRawX(), (int)event.getRawY())) { Log.d("focus","touchevent"); v.clearFocus(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } } } return super.dispatchTouchEvent(event); } |
现在会发生什么事情,当用户点击外面然后首先调用dispatchTouchEvent然后将从editext清除焦点现在你的OnFocusChangeListener将被调用焦点已被更改现在你可以做任何你想做的事情希望它工作
活动
1 2 3 4 5 | @Override public boolean dispatchTouchEvent(MotionEvent ev) { ScreenUtils.hideKeyboard(this, findViewById(android.R.id.content).getWindowToken()); return super.dispatchTouchEvent(ev); } |
ScreenUtils
1 2 3 4 | public static void hideKeyboard(Context context, IBinder windowToken) { InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(windowToken, InputMethodManager.HIDE_NOT_ALWAYS); } |
这可能是旧的但我通过实现自定义类来实现这一点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class DismissKeyboardListener implements OnClickListener { Activity mAct; public DismissKeyboardListener(Activity act) { this.mAct = act; } @Override public void onClick(View v) { if ( v instanceof ViewGroup ) { hideSoftKeyboard( this.mAct ); } } } public void hideSoftKeyboard(Activity activity) { InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE); imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0); } |
这里的最佳实践是创建一个Helper类,每个容器相对/线性布局都应该实现这一点。
****请注意只有主要容器应该实现这个类(用于优化)****
并像这样实现它:
1 | Parent.setOnClickListener( new DismissKeyboardListener(this) ); |
关键字this是Activity。所以,如果你是片段,你使用像getActivity();
---如果对你帮助大拇指......
---欢呼拉尔夫---
那么,您可以使用此代码,使用您的主要布局ID而不是"mainRelativeLayout"
1 2 3 4 5 6 7 8 9 10 11 12 | //hide Soft keyboard on click outside the input text findViewById(R.id.mainRelativeLayout).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { InputMethodManager im = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE); im.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } }); |
其他想法是在Activity的根视图上覆盖
触摸事件从屏幕上的最前面视图(发生触摸事件的位置)向下调用
但是,在进行此遍历之前,触摸事件会沿着另一条路径行进,从根视图向下看到视图树,直到它到达最前面的视图。通过调用
这个对我来说是最简单的解决方案(由我来解决)。
这是隐藏键盘的方法。
1 2 3 4 5 6 | public void hideKeyboard(View view){ if(!(view instanceof EditText)){ InputMethodManager inputMethodManager=(InputMethodManager)getSystemService(INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(),0); } } |
现在,将活动的父布局的onclick属性设置为上面的方法
1 | android:onClick="hideKeyboard" |
我设法隐藏了
1 2 3 4 5 | 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 } |
我以为这个问题。
首先,我认为setOnTouchListener不是简单的解决方案。
所以我相信dispatchTouchEvent是最简单的解决方案。
1 2 3 4 5 6 7 8 9 10 | public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP) { View v = getCurrentFocus(); if (v instanceof EditText) { InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0); } } return super.dispatchKeyEvent(event); } |
在这里,一个重要的是ACTION_UP。
我假设EditText只显示软键盘,否则不显示键盘。
我在Android5.0.1(LG的G3.cat6)上测试过。
如果你需要拖动检查,长按,...,显示上面的评论。
我在Fernando Camarago的解决方案上略微改变了这一点。在我的onCreate方法中,我将一个onTouchListener附加到根视图,但是将视图而不是活动作为参数发送。
1 2 3 4 5 6 | findViewById(android.R.id.content).setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { Utils.hideSoftKeyboard(v); return false; } }); |
在一个单独的Utils类中......
1 2 3 4 | public static void hideSoftKeyboard(View v) { InputMethodManager imm = (InputMethodManager) v.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } |
你可以尝试下面的方式,它对我很有用:)
这种方式可以应用于Activity或Fragment,它也与ScrollView兼容。
我们将ScrollView作为顶级布局,为内部的LinearLayout声明id parentView,并添加如下两个属性:
1 2 3 | android:id="@+id/parentView" android:clickable="true" android:focusableInTouchMode="true" |
在代码中,编写如下函数:
1 2 3 4 | 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受到影响:
1 2 3 4 5 6 7 8 | parentLayout.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { hideSoftKeyboard(your_activity_name.this); } } }); |
我的解决方案在所有编辑文本的任何活动中隐藏键盘外部点击。没有逐一指定它们。
首先添加布局xml的根视图:
机器人:可点击="真"
机器人:focusableInTouchMode ="真"
接下来,创建一个要隐藏键盘的所有活动的父级Acitvity,并指定onResume()方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Override protected void onResume() { super.onResume(); //getting Root View that gets focus View rootView =((ViewGroup)findViewById(android.R.id.content)). getChildAt(0); rootView.setOnFocusChangeListener(new View.OnFocusChangeListener() { @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { hideKeyboard(AbstractActivity.this); } } }); } |
使用此常规活动(继承功能!)扩展您的活动,这就是所有,每当任何EditText(在任何扩展活动上)失去焦点时,键盘都将被隐藏。
附: hideKeyboard方法:
1 2 3 4 | public static void hideKeyboard(Activity context) { InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow( context.getCurrentFocus().getWindowToken(), 0); } |
context.getCurrentFocus()不需要指定特定的EditText视图。
您可以轻松覆盖活动和片段中的onKey()事件以隐藏键盘。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (keyCode == event.KEYCODE_ENTER) { intiateLoginProcess(); InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(getWindow().getCurrentFocus() .getWindowToken(), 0); return true; } } return false; } |
嘿家伙我有这个问题的简单解决方案,这个解决方案可以用于简单的注册或登录表单。
我的解决方案与我在ios setontouch监听器中实现的主视图相同
activity_main.xml将ID添加到主相对布局
并将此代码添加到您的活动中
1 2 3 4 5 6 7 8 9 10 11 12 | RelativeLayout mainLayout = (RelativeLayout)findViewById(R.id.mainlayout); mainLayout.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { // TODO Auto-generated method stub Log.d("Json Response","Touch outside"); InputMethodManager inputMethodManager = (InputMethodManager) MainActivity.this.getSystemService(Activity.INPUT_METHOD_SERVICE); inputMethodManager.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), 0); return false; } }); |
1 | setupUI((RelativeLayout) findViewById(R.id.activity_logsign_up_RelativeLayout)); |
将方法传递到布局文件中。您必须以XML格式选择公共布局文件。
因为,键盘隐藏适用于整个布局。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public void setupUI(View view) { // Set up touch listener for non-text box views to hide keyboard. if (!(view instanceof EditText)) { view.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { hideSoftKeyboard(Your Context); // Pass your context return false; } }); } //If a layout container, iterate over children and seed recursion. if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { View innerView = ((ViewGroup) view).getChildAt(i); setupUI(innerView); } } } |