最近遇到了一个在 Dialog 中监听键盘弹出与收起事件的需求,经过查询资料再与自己的需求相结合然后思考,最终解决了问题。现将中间遇到的问题与解决办法记录下来。
需求与效果
思路
自定义 Dialog,通过设置 Dialog 的 “windowSoftInputMode” 配合监听 Dialog 所在 Window 的高度变化来判断键盘当前的状态。
实现
布局
1 |
|
style
1 | <style name="Dialog" parent="Theme.AppCompat.Dialog"> |
Dialog
1 | class MyDialog(context: Context, private val callback: Callback) : Dialog(context, R.style.Dialog) { |
添加显示 Dialog 的点击事件
在 Activity 中添加一个按钮,并为它添加点击事件如下:
1 | button.setOnClickListener { |
此时已经可以监听到键盘的弹出与收起事件了,但是仔细看输入框会发现下半部分被键盘盖住了。
解决问题
经过研究发现这与 EditText 的 background 属性有关,先把 android:background="@null"
去掉,效果如下:
那么 background 设置为 null 与默认值的差别在哪里呢?我们通过 EditText 的源码找一下答案。
1 | public class EditText extends TextView { |
从源码中可以看出 EditText 的默认 style 为 com.android.internal.R.attr.editTextStyle
,接下来全局搜索看一下这个 style 的特征:
一路追踪 parent,最终发现顶级 parent 如下:
1 | <style name="Widget.EditText"> |
再全局搜索 editTextBackground
关键字:
从图中可以看出有很多 item 的 name 是 editTextBackground
,随便打开一个,这里就以图中选中的为例,打开文件如下:
1 | <inset xmlns:android="http://schemas.android.com/apk/res/android" |
可以看到是通过 xml 设置了一个 InsetDrawable,这里效果如同给 EditText 设置 padding。所以我们给 EditText 添加 paddingTop 和 paddingBottom,运行后发现效果 OK。
使用 FragmentDialog 注意
因为 FragmentDialog 是一个 Fragment,所以既可以通过 getActivity().getWindow()
也可以使用 dialog.getWindow()
,但是要注意这里应该使用 dialog.getWindow()
,反之将不会有预期效果。