前景:需要开发一个聊天系统,界面需要和微信一样,输完内容直接点发送内容,内容发送完成,但input不失焦,发送可以用input的@confirm事件执行,也可以是在别的dom上绑定发送。遇到两个难点
- 点发送input马上失焦
- input聚焦后,会把页面上顶,聊天内容就被顶走了,看不到了
DOM结构
<view class="content"><view class="chat"><scroll-view scroll-y="true" class="scroll" :scroll-top="scrollTop" scroll-with-animation :show-scrollbar="true"><view class="chat-content" v-for="(item, index) in chatData" :key="index"><view class="chat-list" v-if="item.type == 2"><image class="c-l-head" @click="switchSpeakers(item)" :src="item.head" /><view class="c-l-center">{{ item.content }}</view></view><view class="chat-list-right" v-if="item.type == 1"><view class="c-l-center">{{ item.content }}</view><image class="c-l-head" @click="switchSpeakers(item)" :src="item.head" /></view><view class="caht-time" v-if="item.type == 3"><text class="c-t-time c-t-nobg">{{ item.content }}</text></view></view><view class="kongb" style="height: 14px; flex: 1"></view></scroll-view></view><view class="bottom"><view class="bottom-top"><view class="b-t-l"><image class="bottom-icon" src="/static/chat1.png" /></view><view class="b-t-c"><input class="uni-input" v-model="value" :style="{ marginBottom: isFoucs ? '15px' : '5px' }" confirm-type="send" @click="isChange = true" :focus="isFoucs" @blur="blur" @focus="foucs" @confirm="confirm" placeholder="" /></view><view class="b-t-r"><image class="bottom-icon t-r-icon" src="/static/chat2.png" /><image class="bottom-icon" src="/static/chat3.png" /></view></view></view></view>
CSS
.content {width: 100%;height: 100%;position: absolute;display: flex;flex-direction: column;justify-content: flex-end;background: #ededed;.chat {flex: 1;background: #ededed;width: 100%;position: relative;.scroll {position: absolute;width: 100%;height: 100%;bottom: 0;left: 0;top: 0;display: flex;flex-direction: column;}}.bottom {width: 100%;background: rgba(245, 245, 245, 0.98);position: relative;display: flex;flex-direction: column;padding-bottom: calc(env(safe-area-inset-bottom) + 1rpx);.spokesman {width: 80upx;position: absolute;display: flex;flex-direction: column;justify-content: center;top: -70px;background: #fff;border: 2px solid #fff;left: 20upx;&::after {content: '';width: 16upx;height: 16upx;background: #fff;border-radius: 4upx;transform: rotate(45deg);position: absolute;left: 50%;bottom: -10upx;margin-left: -10upx;}.s-head {width: 80upx;height: 80upx;border-radius: 10upx;}.sp-text {color: #333;font-size: 11px;text-align: center;background: #fff;position: relative;z-index: 2;}}.bottom-top {width: 100%;display: flex;flex-direction: row;padding-top: 7px;border-top: 1px solid #dad7d3;box-sizing: border-box;align-items: flex-start;.b-t-c {flex: 1;.uni-input {height: 40px;flex: 1;padding: 5px 10px;font-size: 16px;background: #ffff;border-radius: 10upx;color: #000;margin-bottom: 5px;box-sizing: border-box;}}.b-t-l {padding: 0 20upx;display: flex;align-items: center;padding-top: 7px;}.b-t-r {padding: 0 20upx;display: flex;align-items: center;padding-top: 7px;.t-r-icon {margin-right: 25upx;}}.bottom-icon {width: 54rpx;height: 54rpx;}}.bottom-k {width: 100%;height: 24px;}}
}
这样写,然后就会上顶,还会输完以后马上失焦
解决失焦问题
属性名 | 类型 | 默认值 | 说明 | 平台差异说明 | 备注 |
---|---|---|---|---|---|
confirm-hold | Boolean | false | 点击键盘右下角按钮时是否保持键盘不收起 | App(3.3.7+)、H5 (3.3.7+)、微信小程序、支付宝小程序、百度小程序、QQ小程序、京东小程序 | 使用input自带的发送按钮,添加这个属性后,发送完成后就不会失焦了 |
以上测试还有两个问题
- 聊天内容上顶
- input输入框位置不对
聊天内容上顶可以添加adjust-position这个属性
属性名 | 类型 | 默认值 | 说明 | 平台差异说明 | 备注 |
---|---|---|---|---|---|
adjust-position | Boolean | true | 键盘弹起时,是否自动上推页面 | App-Android(vue 页面 softinputMode 为 adjustResize 时无效,使用 x5 内核时无效)、微信小程序、百度小程序、QQ小程序、京东小程序 | ~ |
添加后,不会上顶了,但是这样也把input给挡住了,无法看到input框了, 因为我们设置的.input样式是position:fixed; bottom:0;
找到问题解决问题,知道是fixed的bottom:0,导致input框被键盘遮住,那就获取这个键盘高度,并且,把.input的bottom:键盘高度就解决这个问题了
<!-- Dom结构 -->
<view class="bottom" :style="{bottom:bottomHeight}">
input框dom
<view>
methods: {// 键盘弹出时执行keyboardheightchange(ev){const res_keyboard = uni.getSystemInfoSync();// 获取键盘高度 - 刘海屏手机下方的空白高度 = input的bottom高度const h = (ev.detail.height ? ev.detail.height - res_keyboard.safeAreaInsets.bottom : 0)this.bottomHeight = h + 'px';// 计算聊天内容主体高度this.computedHeight(h)},// 计算高度computedHeight(bottomHeight) {let that = this;that.screenHeight = '100vh';const query = uni.createSelectorQuery().in(this); //这样写就只会选择本页面组件的类名box的query.select('.chat').boundingClientRect(); // 聊天内容主体query.select('.bottom').boundingClientRect(); // input框入框主体query.exec(function(res) {if (bottomHeight) {// 键盘弹出that.screenHeight = res[0].height - res[1].height - bottomHeight + 'px';this.scrollTop += 100;} else {// 键盘收起 that.screenHeight = res[0].height - res[1].height + 'px';}});},}
最后,完成此功能