输入框被软键盘遮挡的解决办法(Ability、Dialog都可以) 原创 精华
没用的喵叔
发布于 2021-7-8 08:56
浏览
5收藏
目录
先放代码:
-----> 喵叔catuncle / TestTextField <-----
因为后来代码更新了,所以文章内容只是解决问题的一个思路。以代码为准!
理论上讲通过自定义Adapter,可以适配所有的情况
处理前后对比
处理前 | 处理前后 |
---|---|
![]() |
![]() |
问题现状
安卓上面,输入框被软键盘遮挡,很简单
这样,软键盘弹出后,输入框就会自动上移。
鸿蒙上也有类似的设置,但是貌似没效果:
解决过程
原理:
- 布局文件用ScrollView包起来
- 监听根布局大小变化,变小了,证明输入法弹出了。
- 滚动ScrollView,使当前焦点控件显示在软键盘上方。
核心代码:
----> 完整代码见文末 <----
特别说明: 滚动操作为什么要delay 100毫秒?因为点击一个输入框Component.LayoutRefreshedListener
有时会反复调用多次,而且间隔时间小于10毫秒,所以会造成滚动距离不准确。用postTask之后,每次调用的时候会把之前的task remove掉,以最新的一次为准。
计算滚动距离
其中上面的大红框是decorRect(即当前Ability可视区域),下面的大黑框是输入法显示区域。其中,软键盘弹出后,输入框被软键盘挡住,图中的小红框。
所以,要滚动的距离就是图中的C=A-B
。
可以优化的点:(有兴趣的朋友可以试一下,记得在评论区分享你的结果)
- 如果是Dialog中的输入框,当前的计算方法是否正确?
- 如果不用ScrollView,还有别的解决办法吗?
- 抽取出工具类或工具方法,代码复用。
2021-08-02优化
- 封装了TextFieldHelper工具类
自动上移TextField。监听软键盘显示、隐藏。
- 对于不同的布局处理TextField的移动有差异,所以定义了ITFHAdapter来适配。
我已经预定义了
ScrollViewTFHAdapter
、DirectionTFHAdapter
处理根布局为ScrollView
、DirectionalLayout
的情况。预定义了
DlgTFHAdapter
处理CommonDialog
的情况(通过debug发现CommonDialog的根布局也是ScrollView,但是Dialog有一些特殊情,所以通过继承ScrollViewTFHAdapter来实现)
©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-8-2 16:29:36修改
赞
5
收藏 5
回复
5
5
5
相关推荐
很有用的分享,回去试一下。
就贼细节
此类应用场景,鸿蒙应该有类似安卓上的简单原生配置方法,不知鸿蒙是否已实现。(楼主说了getWindow().setInputPanelDisplayType(WindowManager.LayoutConfig.INPUT_ADJUST_PAN);配置无效)
这个解决办法在横屏下会报错诶
Selected stacktrace:
java.lang.NullPointerException: Attempt to invoke virtual method 'int[] ohos.agp.components.Component.getLocationOnScreen()' on a null object reference
at com.liny.hmos.reallinystools.slice.MainAbilitySlice$MyTask.run(MainAbilitySlice.java:46)
at ohos.eventhandler.EventHandler.distributeEvent(EventHandler.java:887)
at ohos.eventhandler.O00000O.run(PlatformEventRunner.java:73)
at android.os.Handler.handleCallback(Handler.java:900)
at android.os.Handler.dispatchMessage(Handler.java:103)
at android.os.Looper.loop(Looper.java:219)
at android.app.ActivityThread.main(ActivityThread.java:8668)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)
报错的位置↓
现在可以了