效果图
随着输入的文本自动增加高度,键盘上方自定义菜单布局,随键盘弹起
点击编辑框,自动滚动到焦点处输入
布局层次
<ConstraintLayout>
<ScrollView>
<LinearLayout>
<Edittext/>
<自定义布局/>
</LinearLayout>
</ScrollView>
<键盘上方自定义布局/>
</ConstraintLayout>
想要实现自动焦点定位,需要手动计算滚动距离,系统也有自带的滚动效果,不过因为这里有自定义布局,所以不兼容
系统原生自带了键盘弹起顶起布局的方式,并且点击 edittext 后 scrollView 里的 edittext 会自动滚动定位到焦点区域
有它的便捷也有它的问题,比如自定义键盘上方的布局后,定位不准确,因为自定义的布局不属于键盘,系统不会计算在内,而且自动定位部分手机不起效果,需要做兼容
滚动后内容区域不在键盘上方自定义布局上,而是滚动到键盘上方,缺少了自定义布局的那段高度
滚动方法很简单,直接调用 scrollView.smoothScrollTo(0, scrollTo) 方法就行
然后需要提前测量好键盘上方布局的高度跟键盘弹起的高度
键盘直接使用 Blankj 工具类 KeyboardUtils 监听,布局高度直接测量就行
接下来监听键盘弹起状态 onSoftInputChanged,每次弹起键盘手动给 scrollView 设置 bottomMargin,为了让布局在键盘弹起时在键盘上方位置,如果有自定义布局需要把布局高度也计算上
到这里键盘弹起结束,接下来进入核心,自动滚动定位焦点
首先是获取到当前焦点的精确坐标,有了坐标才能跳转
一开始我尝试了 touch 触摸事件,通过点击的位置来获取坐标,计算滑动距离,不过这个方案很快被推翻
因为不是很准确,加上内容是自适应高度,滑动距离过长时问题多
后来发现可以通过 getLineForOffset 方法获取编辑框当前的行数,然后在通过 getLineBounds 方法获取行坐标
获取坐标后需要计算出 scrollView 滑动的距离
滑动距离 = 当前坐标 - 键盘弹起高度 + 自定义布局高度
如果没有自定义布局就不用算
private fun scrollEdit() { //当前光标的坐标-键盘高度 val scrollTo = getCurrentEditY() - boardHeight + menuHeight mBinding.scrollView.post { //计算实际滚动的位置 mBinding.scrollView.smoothScrollTo(0, scrollTo) } }
得到滚动距离后直接在 onTextChanged 监听里去调用上面的方法就行了,此时只要文本更改就会重新定位,自动滚动到你输入的内容区域上
注意点
1、焦点自动定位问题
如果存在 ScrollView 嵌套 Edittext,那么会有部分手机系统会自动滚动到焦点位置的情况,但是这不符合我们的自定义需求,毕竟系统定位的不准确,没有导航栏适配,
滚动的位置会出现遮挡键盘上方布局的情况,所以需要重写方法去限制一下
2、导航栏适配问题
因为底部有自定义布局,会跟随键盘弹起,所以需要适配系统导航栏,否则底部自定义布局不好适配
3、自动滚动问题
核心就在于滚动定位,需要自己计算滚动距离,并且在输入的时候自动定位到该区域
并且如果调用滚动方法时,需要在变动之后调用,否则会跟系统测量结果有冲突,也就是在点击后调用 post 方法,在里面做滚动操作
文章来源: 博客园
- 还没有人评论,欢迎说说您的想法!