效果图

随着输入的文本自动增加高度,键盘上方自定义菜单布局,随键盘弹起

点击编辑框,自动滚动到焦点处输入

布局层次

<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 方法,在里面做滚动操作

 

posted on 2023-02-19 09:41  翻滚的咸鱼  阅读(181)  评论(0编辑  收藏  举报