我正在参与掘金创作者训练营第4期,点击了解活动详情,一起学习吧!
前情提要
小程序中实现聊天页面的输入框分几步:
- 写一个输入框
- 定位在底部
- 绑定个事件
- 你以为这就万事大吉了?nonono,当你的页面存在自定义导航的时候就会出现这样的情况:
| 机型 | 效果 | 机型 | 效果 |
|---|---|---|---|
| android | ios |
效果图中顶部导航为自定义导航从效果图中可以看到,在存在定义导航的界面,输入框获取焦点时自定义导航会被移除界面,这并不是我们想要的效果。
问题分析
原因:通过 官方文档 可知,input输入框属性adjust-position 属性默认为 true,在获取焦点时会将页面整体上移,以实现键盘弹出不遮挡获取焦点的输入框的目的。但此时自定义的顶导航也是页面的一部分,所以在上移的时候 自定义导航被移出了界面。
Tips: 即使自定义导航采用的是
position:fixed仍然会被移出界面
解决方案
这个效果并不是我们想要的,如何解决呢?
- 首先,肯定是先关掉这个默认上移的行为
- 其次,在输入框获取焦点的时候,我们手动调节输入框的位置来匹配
软键盘弹起的高度
cursor-spacing
官方定义:指定光标与键盘的距离,取 input 距离底部的距离和 cursor-spacing 指定的距离的最小值作为光标与键盘的距离;最低版本:1.0.0
看上去符合我们调节距离的目的,只要我们在获取焦点的时候,拿到键盘的高度,设置该属性即可实现,输入框随着键盘弹起的目的;行不行,测一波就知道了先设置个 200px 看看效果
| 型号 | 效果图 | 型号 | 效果图 |
|---|---|---|---|
| android | ios |
相同的代码,在ios下设置的200没有效果,所以ios下取最小值是个0?这个鬼定义跟文言文一样也不知道他这个最小距离指的是啥!!果断放弃
JS 设置定位 bottom值,来调解输入框和键盘的位置关系
-
给输入框绑定
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` }); } -
上真机调试:
型号 效果图 型号 效果图 android ios
看效果没啥大毛病了,唯一的缺点就是 软键盘先弹起,再出现输入框;中间有一个短暂的延迟,这是由于获取键盘高度的事件,要在键盘弹起之后触发;目前没有想到比较好的解决办法; 不过通过动态调节bottom的方法,已经解决了 输入框获取焦点时对自定义导航的影响
补充
- 输入框分为两种,input输入框和textarea输入框
- input 输入框在使用上述方法没有问题
- textarea 需要注意,其默认会带有一个 完成按钮,在使用上述方法时,需要将其隐藏避免其高度遮挡输入框
- 最后别忘了给输入框底部加上安全区,来兼容ios底部的边线
在测试的过程中还发现了一个奇怪的现象:
| 行为描述 | 行为效果图 | 行为描述 | 行为效果图 |
|---|---|---|---|
| ios 默认输入框未加任何属性、无自定义导航,在输入框获取焦点的第三次顶部导航会上移一次 | 同样的代码安卓下面就不会有这个现象 | ||
| ios 默认输入框未添加任何属性、无自定义导航,给输入款增加了 safe-area css后,输入框会从父元素中溢出 | 同样的代码安卓下输入框在获取焦点是不会溢出父元素 |
以上就是在实际开发过程中遇到问题的解题过程,如果有小伙伴有更好的解决方法,欢迎在评论区交流。