好的每个人都知道要隐藏你需要实现的键盘:
InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
但这里最重要的是当用户触摸或选择任何其他不是 EditText
或softKeyboard的地方时如何隐藏键盘?
我尝试在我的父 Activity
上使用 onTouchEvent()
,但这只有在用户触摸任何其他视图以外且没有滚动视图时才有效 .
我试图实现触摸,单击,集中监听器而没有任何成功 .
我甚至尝试实现自己的scrollview来拦截触摸事件,但我只能获取事件的坐标而不是点击的视图 .
有没有一种标准的方法来做到这一点?在iPhone中它真的很容易 .
30 回答
您可以轻松地覆盖活动和片段中的onKey()事件以隐藏键盘 .
以下代码段只是隐藏了键盘:
您可以将其放在实用程序类中,或者如果要在活动中定义它,请避免使用activity参数,或者调用
hideSoftKeyboard(this)
.最棘手的部分是何时调用它 . 您可以编写一个迭代活动中每个
View
的方法,并检查它是否为instanceof EditText
,如果它没有向该组件注册setOnTouchListener
,那么一切都将落实到位 . 如果你想知道如何做到这一点,事实上它很简单 . 这是你做的,你写一个像下面这样的递归方法,实际上你可以用它来做任何事情,比如设置自定义字体等......这是方法这就是全部,只需在活动中
setContentView
之后调用此方法即可 . 如果您想知道将传递什么参数,它是父容器的id
. 将id
分配给父容器,如<RelativeLayoutPanel android:id="@+id/parent"> ... </RelativeLayout>
并致电
setupUI(findViewById(R.id.parent))
,就是这样 .如果要有效地使用它,可以创建扩展
Activity
并将此方法放入,并使应用程序中的所有其他活动扩展此活动并在onCreate()
方法中调用其setupUI()
.希望能帮助到你 .
如果您使用多个活动,则为父布局定义公共ID,如
<RelativeLayout android:id="@+id/main_parent"> ... </RelativeLayout>
然后从
Activity
扩展一个类并在其OnResume()
中定义setupUI(findViewById(R.id.main_parent))
并扩展此类而不是``Activityin your program
您可以通过执行以下步骤来实现此目的:
正如下面的一条评论中所指出的,如果父视图是ScrollView,这可能不起作用 . 对于这种情况,可以在ScrollView正下方的视图上添加clickable和focusableInTouchMode .
我发现接受的答案有点复杂 .
这是我的解决方案 . 将
OnTouchListener
添加到主布局,即:并将以下代码放在onTouch方法中 .
这样您就不必遍历所有视图 .
我还有一个解决方案来隐藏键盘:
这里
HIDE_IMPLICIT_ONLY
位于showFlag
和0
位置HIDE_IMPLICIT_ONLY
. 它将强制关闭软键盘 .好吧,我设法解决了这个问题,我在我的活动上覆盖了dispatchTouchEvent,在那里我使用以下来隐藏键盘 .
EDIT: getFields()方法只是一个返回视图中包含文本字段的数组的方法 . 为了避免在每次触摸时创建这个数组,我创建了一个名为sFields的静态数组,它在getFields()方法中返回 . 此数组在onStart()方法上初始化,例如:
sFields = new EditText[] {mUserField, mPasswordField};
它并不完美,拖动事件时间只是基于启发式,所以有时它在执行长文件时不会隐藏,我还完成了创建一个方法来获取每个视图的所有editTexts;否则键盘会在单击其他EditText时隐藏和显示 .
仍然,欢迎更清洁和更短的解决方案
使用OnFocusChangeListener .
例如:
Update :您也可以在活动中覆盖
onTouchEvent()
并检查触摸的坐标 . 如果坐标在EditText之外,则隐藏键盘 .我在Activity中实现了dispatchTouchEvent来执行此操作:
我测试了它,效果很好!
在任何Activity中覆盖公共布尔dispatchTouchEvent(MotionEvent事件)(或扩展Activity类)
这就是你需要做的一切
它太简单了,只需通过以下代码使您最近的布局可点击:
然后为该布局编写一个方法和一个OnClickListner,这样当触摸最上面的布局时,它会调用一个方法,在这个方法中你将编写代码来解除键盘 . 以下是两者的代码; //你必须在OnCreate()中写这个
从listner调用的方法: -
我知道这个帖子已经很老了,正确的答案似乎是有效的,并且有很多有效的解决方案,但我认为下面提出的方法可能会带来效率和优雅的额外好处 .
我的所有活动都需要这种行为,因此我创建了一个继承自Activity类和"hooked" dispatchTouchEvent函数的类CustomActivity . 主要有两个条件需要照顾:
如果焦点没有改变,有人在当前输入字段之外点击,那么解雇IME
如果焦点已更改且下一个焦点元素不是任何类型的输入字段的实例,则忽略IME
这是我的结果:
附注:此外,我将这些属性分配给根视图,从而可以清除每个输入字段的焦点,并防止输入字段聚焦于活动启动(使内容视图成为“焦点捕获器”):
我修改了Andre Luis IM的解决方案我实现了这个:
我创建了一个实用工具方法来隐藏软键盘,就像Andre Luiz IM所做的那样:
但是,不是为每个视图注册一个OnTouchListener,而是性能不佳,我只为root视图注册了OnTouchListener . 由于事件一直消耗直到被消耗(EditText是默认使用它的视图之一),如果它到达根视图,那是因为它没有被消耗,所以我关闭了软键盘 .
我喜欢调用htafoya制作的
dispatchTouchEvent
的方法,但是:我没有知道为什么需要测量停机时间?)
我不喜欢在每次视图更改时注册/取消注册所有EditTexts(在复杂的层次结构中可能有很多视图更改和edittexts)
所以,我做了一些更简单的解决方案:
有一个缺点:
从一个
EditText
切换到另一个EditText
使键盘隐藏和重新显示 - 在我的情况下,它需要这样,因为它显示您在两个输入组件之间切换 .Plea: 我认识到我没有影响力,但请认真对待我的回答 .
Problem: 单击远离键盘或使用最少代码编辑文本时关闭软键盘 .
Solution: 外部库称为 Butterknife.
一线解决方案:
更易读的解决方案:
Explanation: 将OnClick侦听器绑定到活动的XML布局父ID,以便对布局(而不是编辑文本或键盘)上的任何单击都将运行将隐藏键盘的代码片段 .
Example: 如果你的布局文件是R.layout.my_layout而你的布局ID是R.id.my_layout_id,那么你的Butterknife绑定调用应该如下所示:
Butterknife Documentation Link: http://jakewharton.github.io/butterknife/
Plug: Butterknife将彻底改变您的Android开发 . 考虑一下 .
Note: 无需使用外部库Butterknife即可实现相同的结果 . 只需将OnClickListener设置为父布局,如上所述 .
显示/隐藏软键盘的方法
我希望他们有用
这是fje答案的另一个变体,它解决了sosite提出的问题 .
这里的想法是在Activity的
dispatchTouchEvent
方法中处理向下和向上的动作 . 在向下动作中,我们记下当前聚焦的视图(如果有的话)以及触摸是否在其中,保存这些信息以供稍后使用 .在up动作中,我们首先发送,以允许另一个视图可能成为焦点 . 如果在此之后,当前聚焦的视图是最初聚焦的视图,并且向下触摸在该视图内,则我们使键盘保持打开状态 .
如果当前聚焦的视图与最初聚焦的视图不同并且它是
EditText
,那么我们也将键盘保持打开状态 .否则我们关闭它 .
所以,总结一下,这个工作原理如下:
当触摸当前聚焦
EditText
时,键盘保持打开状态从焦点
EditText
移动到另一个EditText
时,键盘保持打开状态(不关闭/重新打开)当触摸当前聚焦的
EditText
之外的任何地方时,键盘关闭当长按
EditText
以调出上下文操作栏(使用剪切/复制/粘贴按钮)时,键盘保持打开状态,即使UP操作发生在聚焦EditText
之外(向下移动以便为驾驶室) . 但请注意,当您点击CAB中的按钮时,它将关闭键盘 . 这可能是也可能不是可取的;如果你想从一个字段剪切/复制并粘贴到另一个字段,那就是 . 如果你想要粘贴回相同的EditText
,它就不会 .当焦点
EditText
位于屏幕底部并且您长按一些文本以选择它时,EditText
会保持焦点,因此键盘会按照您的需要打开,因为我们会对向下操作进行"touch is within view bounds"检查,而不是行动起来 .使用TextInputEditText的更多 Kotlin & Material Design 方法(此方法也与EditTextView兼容)...
1.制作父视图(内容视图)您的活动/片段)可通过添加以下属性进行单击和聚焦
2.为所有View创建扩展(例如,在ViewExtension.kt文件中):
3.创建继承TextInputEditText的BaseTextInputEditText . 在视图未聚焦时,实现onFocusChanged方法以隐藏键盘:
4.只需在XML中调用全新的自定义视图:
就这样 . No need to modify your controllers (片段或活动)来处理这种重复的情况 .
对于这个简单的要求,我发现接受的答案有点复杂 . 这对我有用,没有任何故障 .
有一种更简单的方法,基于iPhone同样的问题 . 只需覆盖触摸事件的背景布局,其中包含编辑文本 . 只需在活动的OnCreate中使用此代码(login_fondo是根布局):
我已经改进了方法,将以下代码放在一些UI实用程序类中(最好不一定),以便可以从所有Activity或Fragment类访问它以实现其目的 .
然后说例如你需要从活动中调用它,如下调用它;
注意
这为我们提供了当前组的根视图(您不能在根视图上设置id) .
干杯:)
尝试将stateHidden设置为您的活动
windowSoftInputMode
值http://developer.android.com/reference/android/R.attr.html#windowSoftInputMode
例如,对于您的活动:
活动
ScreenUtils
这可能是旧的,但我通过实现自定义类来实现这一点
这里的最佳实践是创建一个Helper类,每个容器相对/线性布局都应该实现这一点 .
请注意只有主要容器应该实现这个类(用于优化)
并像这样实现它:
关键字,这是活动 . 因此,如果您使用片段,则使用getActivity();
---如果对你有帮助的话......赞不绝口 - 拉尔夫---
我在Fernando Camarago的解决方案上略微改变了这一点 . 在我的onCreate方法中,我将一个onTouchListener附加到根视图,但是将视图而不是activity作为参数发送 .
在一个单独的Utils类中......
这是fje答案的略微修改版本,大部分都是完美的 .
此版本使用ACTION_DOWN,因此执行滚动操作也会关闭键盘 . 除非您单击另一个EditText,否则它也不会传播该事件 . 这意味着单击EditText外的任何位置,即使是另一个可点击的,也只需关闭键盘即可 .
我这样做了:
Hide keyboard code :
Done
要解决此问题,您需要首先使用该Edittext的setOnFocusChangeListener
然后你需要做的是在包含Edittext的activity中覆盖dispatchTouchEvent,参见下面的代码
现在会发生什么事情,当用户点击外面然后首先调用dispatchTouchEvent然后将从editext清除焦点现在你的OnFocusChangeListener将被调用焦点已经改变现在你可以做任何你想做的事情希望它工作
只需在@Overide类中添加此代码即可
其他想法是在您的Activity的根视图上覆盖
onInterceptTouchEvent
方法 .触摸事件从屏幕上的最前面视图(发生触摸事件的位置)向下调用
onTouch
方法的视图堆栈,直到任何视图返回true,表示触摸事件已被消耗 . 由于许多视图默认使用触摸事件(例如EditText
或TextView
的情况),因此事件无法访问Activity的根视图onTouch
方法 .但是,在进行此遍历之前,触摸事件会沿着另一条路径行进,从根视图向下看到视图树,直到它到达最前面的视图 . 通过调用
onInterceptTouchEvent
来完成此遍历 . 如果方法返回true,它会拦截事件...... nahhh,但这有点诡计,我认为你不想这样做也不知道细节 . 您需要知道的是,您可以在Activity的根视图上覆盖此方法,并在必要时放置代码以隐藏键盘 .