uniapp 实现聊天页面 textarea固定在底部且高度自增
在使用uniapp實現一個IM即時通訊系統的時候聊天界面是十分重要的,參考微信QQ的界面,決定模仿一個差不多的出來。
對于消息內容,肯定就是使用scroll-view組件了,發送消息的輸入框則固定在底部,且輸入框使用textarea組件。
頁面效果如下(模擬器的原因導致軟鍵盤附近有黑色):
textarea自動增高,當內容輸入過多會,輸入框會向上增高一點,與QQ的輸入是差不多的。
ps: 上面的黑色背景是scroll-view,此處并沒有填充消息
對于這種效果,在APP端是比較好實現的
頁面:
<template><view><u-navbar leftIconColor="#FFFFFF" bgColor="#3c9cff" @leftClick="handleLeftClick"><view slot="center"><text style="color: #FFFFFF;">聊天界面</text></view></u-navbar><view style="width: 100%;background-color: #000000;"><scroll-view :style="{height: height+'px'}" scroll-y></scroll-view></view><view class="footer" ref="footer" id="footer"><view class="content-wrap"><textarea class="content" v-model="text" maxlength="-1" auto-height /></view><view class="btn-wrap"><button class="btn" :disabled="disable" :class="{'disabled': disable}" @click="handleSend">發送</button></view></view></view> </template>這個頁面我是自定義navbar,并且使用的是uview的組件
class,id,ref值為footer的就是固定在底部的輸入框與按鈕,之所以有class,id,ref主要是用class設置樣式,ref,id是用來獲取固定在底部的元素的高度,h5支持vue的this.$refs這種形式但是App端不支持,只能使用uniapp自帶的元素選擇器
對于樣式:
<style>.footer {width: 100%;background-color: #E9EDF4;display: flex;position: fixed;bottom: 0;}.footer .content-wrap {width: 78%;margin-left: 2%;}.footer .content {width: 100%;box-sizing: border-box;margin: 14rpx 0;background-color: #FFFFFF;border-radius: 30rpx;padding: 16rpx;caret-color: #01B4FE;}.footer .btn-wrap {width: 18%;margin-right: 2%;}.footer .btn {width: 15%;height: 65rpx;font-size: 26rpx;margin-left: 2%;background-color: #01B4FE;color: #FFFFFF;position: fixed;bottom: 14rpx;border: 0;outline: none;}.footer .btn-wrap .disabled {background-color: #aae8f5;}/deep/ .uni-textarea-wrapper {max-height: 180rpx;} </style>/deep/ .uni-textarea-wrapper這個才是讓textarea自動增高但是會增高到一定高度,不至于讓textarea因為內容的增多而一直增高
當輸入框獲取焦點時會彈出軟鍵盤,在APP端很容易把頁面上面的部分頂出去,所以需要在page.json配置一下:
{"path" : "pages/test/test-chat/test-chat","style" : {"navigationBarTitleText": "測試chat","enablePullDownRefresh": false,"navigationStyle":"custom",//App端的配置"app-plus":{"softinputMode":"adjustResize"}}}并且需要監聽鍵盤高度變化的事件,讓scroll-view的高度也隨之變化,不然你的軟鍵盤就會遮擋住scroll-view一些內容:
<script> export default {data() {return {text: '',height: 0,pageHeight: 0,disable: true,footerHeight: 0,keyBoardHeight: 0,messages: [],}},watch: {//監聽text,當他有值時發送按鈕才可以點擊text(newVal) {if (newVal.trim() != '') {this.disable = false} else {this.disable = true}}},onReady() {//獲取整個頁面的高度,從而計算出頁面可用的高度,因為使用了自定義的navbar所以this.pageHeight不是單純的res.windowHeight。(ps: uview組件的navbar高度是固定的44px,不包括statusBarHeight)uni.getSystemInfo({success: (res) => {this.pageHeight = res.windowHeight - res.statusBarHeight - 44}})},onLoad() {this.initListener()},onUnload() {this.destoryListener()},mounted() {//這里獲取footer元素的高度,根據不同平臺用的方式不同,對于uniapp的dom定位方法應該是通用的。特別注意,一定要在this.$nextTick方法里寫,不然可能頁面還沒渲染出footer元素this.$nextTick(() => {// #ifdef H5this.footerHeight = this.$refs.footer.$el.offsetHeightthis.height = this.pageHeight - this.footerHeight// #endif// #ifdef APP-PLUSuni.createSelectorQuery().in(this).select("#footer").boundingClientRect((data) => {this.footerHeight = data.heightthis.height = this.pageHeight - this.footerHeight}).exec()// #endif})},methods: {initListener() {//監聽鍵盤的高度變化,讓sroll-view的高度隨之變化uni.onKeyboardHeightChange(res => {let keyBoardHeight = res.heightif (this.keyBoardHeight == 0 && keyBoardHeight > 0) {this.keyBoardHeight = keyBoardHeight}if (keyBoardHeight > 0) {this.height = this.height - this.keyBoardHeight} else {this.height = this.height + this.keyBoardHeight}})},destoryListener() {uni.offKeyboardHeightChange((res) => {console.log("offKeyboardHeightChange...")})},handleLeftClick() {},handleSend() {}} } </script>對于h5端,在uniapp中沒有找到如何獲取h5軟鍵盤的高度的api,所以在移動端的瀏覽器訪問時,scroll-view的高度暫時無法隨軟鍵盤彈出而變化,但是影響也不是很大,就是在輸入消息時,無法讓scroll-view的最后一條消息顯示在輸入框的上面。
最后貼出頁面的完整代碼,以及page.json的配置:
<template><view><u-navbar leftIconColor="#FFFFFF" bgColor="#3c9cff" @leftClick="handleLeftClick"><view slot="center"><text style="color: #FFFFFF;">聊天界面</text></view></u-navbar><view style="width: 100%;background-color: #000000;"><scroll-view :style="{height: height+'px'}" scroll-y></scroll-view></view><view class="footer" ref="footer" id="footer"><view class="content-wrap"><textarea class="content" v-model="text" maxlength="-1" auto-height /></view><view class="btn-wrap"><button class="btn" :disabled="disable" :class="{'disabled': disable}" @click="handleSend">發送</button></view></view></view> </template><script>import myMsg from '@/components/my-msg/my-msg.vue'export default {data() {return {text: '',height: 0,pageHeight: 0,disable: true,footerHeight: 0,keyBoardHeight: 0,messages: [],}},components: {"my-msg": myMsg},watch: {text(newVal) {if (newVal.trim() != '') {this.disable = false} else {this.disable = true}}},onReady() {uni.getSystemInfo({success: (res) => {this.pageHeight = res.windowHeight - res.statusBarHeight - 44}})},onLoad() {this.initListener()},onUnload() {this.destoryListener()},mounted() {this.$nextTick(() => {// #ifdef H5this.footerHeight = this.$refs.footer.$el.offsetHeightthis.height = this.pageHeight - this.footerHeight// #endif// #ifdef APP-PLUSuni.createSelectorQuery().in(this).select("#footer").boundingClientRect((data) => {this.footerHeight = data.heightthis.height = this.pageHeight - this.footerHeight}).exec()// #endif})},methods: {initListener() {uni.onKeyboardHeightChange(res => {let keyBoardHeight = res.heightif (this.keyBoardHeight == 0 && keyBoardHeight > 0) {this.keyBoardHeight = keyBoardHeight}if (keyBoardHeight > 0) {this.height = this.height - this.keyBoardHeight} else {this.height = this.height + this.keyBoardHeight}})},destoryListener() {uni.offKeyboardHeightChange((res) => {console.log("offKeyboardHeightChange...")})},handleLeftClick() {},handleSend() {}}} </script><style>.footer {width: 100%;background-color: #E9EDF4;display: flex;position: fixed;bottom: 0;}.footer .content-wrap {width: 78%;margin-left: 2%;}.footer .content {width: 100%;box-sizing: border-box;margin: 14rpx 0;background-color: #FFFFFF;border-radius: 30rpx;padding: 16rpx;caret-color: #01B4FE;}.footer .btn-wrap {width: 18%;margin-right: 2%;}.footer .btn {width: 15%;height: 65rpx;font-size: 26rpx;margin-left: 2%;background-color: #01B4FE;color: #FFFFFF;position: fixed;bottom: 14rpx;border: 0;outline: none;}.footer .btn-wrap .disabled {background-color: #aae8f5;}/deep/ .uni-textarea-wrapper {max-height: 180rpx;} </style> {"path" : "pages/test/test-chat/test-chat","style" : {"navigationBarTitleText": "測試chat","enablePullDownRefresh": false,"navigationStyle":"custom",//App端的配置"app-plus":{"softinputMode":"adjustResize"}}}總結
以上是生活随笔為你收集整理的uniapp 实现聊天页面 textarea固定在底部且高度自增的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Layui制作界面及功能
- 下一篇: 算法导论 3.2-1 关于单调递增函数的