解决:小程序输入框adjust-position=true默认行为对自定义导航的影响

4,012 阅读4分钟

我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!

前情提要

小程序中实现聊天页面的输入框分几步:

  1. 写一个输入框
  2. 定位在底部
  3. 绑定个事件
  4. 你以为这就万事大吉了?nonono,当你的页面存在自定义导航的时候就会出现这样的情况:
机型效果机型效果
androidandroid-bug.gifiosios-bug.gif

效果图中顶部导航为自定义导航从效果图中可以看到,在存在定义导航的界面,输入框获取焦点时自定义导航会被移除界面,这并不是我们想要的效果。

问题分析

原因:通过 官方文档 可知,input输入框属性adjust-position 属性默认为 true,在获取焦点时会将页面整体上移,以实现键盘弹出不遮挡获取焦点的输入框的目的。但此时自定义的顶导航也是页面的一部分,所以在上移的时候 自定义导航被移出了界面。

Tips: 即使自定义导航采用的是 position:fixed 仍然会被移出界面

解决方案

这个效果并不是我们想要的,如何解决呢?

  1. 首先,肯定是先关掉这个默认上移的行为
  2. 其次,在输入框获取焦点的时候,我们手动调节输入框的位置来匹配 软键盘 弹起的高度

cursor-spacing

官方定义:指定光标与键盘的距离,取 input 距离底部的距离和 cursor-spacing 指定的距离的最小值作为光标与键盘的距离;最低版本:1.0.0

看上去符合我们调节距离的目的,只要我们在获取焦点的时候,拿到键盘的高度,设置该属性即可实现,输入框随着键盘弹起的目的;行不行,测一波就知道了先设置个 200px 看看效果

型号效果图型号效果图
androidcursor-spacing-android.gifioscursor-spacing-ios.gif

相同的代码,在ios下设置的200没有效果,所以ios下取最小值是个0?这个鬼定义跟文言文一样也不知道他这个最小距离指的是啥!!果断放弃

JS 设置定位 bottom值,来调解输入框和键盘的位置关系

  1. 给输入框绑定 bindfocus 事件,获取键盘高度,动态设置输入框父盒子定位 bottom 属性值等于键盘高度(让输入框刚好位于键盘上边缘),给输入框绑定 bindblur 事件,失去焦点时重置输入框父盒子 bottom 属性(让其重新定位在页面底部)

    <view class="message-fuc" style="{{inputBoxStyle}}">
      <input
        value="{{sendText}}" 
        placeholder="请输入..."
        adjust-position="{{false}}"
        bindblur="textBlur"
        bindfocus="textFocus"
        class="message-input"/>
      <button>发送</button>
    </view>
    
      textFocus(e){
        const height = e.detail.height;
        this.setData({ inputBoxStyle: `bottom:${height}px` });
      },
      textBlur(){
        this.setData({ inputBoxStyle: `bottom:0` });
      }
    
  2. 上真机调试:

    型号效果图型号效果图
    androidandroid-bottom.gifiosios-bottom.gif

看效果没啥大毛病了,唯一的缺点就是 软键盘先弹起,再出现输入框;中间有一个短暂的延迟,这是由于获取键盘高度的事件,要在键盘弹起之后触发;目前没有想到比较好的解决办法; 不过通过动态调节bottom的方法,已经解决了 输入框获取焦点时对自定义导航的影响

补充

  1. 输入框分为两种,input输入框和textarea输入框
  • input 输入框在使用上述方法没有问题
  • textarea 需要注意,其默认会带有一个 完成按钮,在使用上述方法时,需要将其隐藏避免其高度遮挡输入框
  1. 最后别忘了给输入框底部加上安全区,来兼容ios底部的边线

在测试的过程中还发现了一个奇怪的现象:

行为描述行为效果图行为描述行为效果图
ios 默认输入框未加任何属性、无自定义导航,在输入框获取焦点的第三次顶部导航会上移一次amazing-ios-1.gif同样的代码安卓下面就不会有这个现象amazing-android-1.gif
ios 默认输入框未添加任何属性、无自定义导航,给输入款增加了 safe-area css后,输入框会从父元素中溢出amazing-ios-2.gif同样的代码安卓下输入框在获取焦点是不会溢出父元素amazing-android-2.gif

以上就是在实际开发过程中遇到问题的解题过程,如果有小伙伴有更好的解决方法,欢迎在评论区交流。