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 H5
			this.footerHeight = this.$refs.footer.$el.offsetHeight
			this.height = this.pageHeight - this.footerHeight
			// #endif
			// #ifdef APP-PLUS
			uni.createSelectorQuery().in(this).select("#footer").boundingClientRect((data) => {
				this.footerHeight = data.height
				this.height = this.pageHeight - this.footerHeight
			}).exec()
			// #endif
		})
	},
	methods: {
		initListener() {
			//监听键盘的高度变化,让sroll-view的高度随之变化
			uni.onKeyboardHeightChange(res => {
				let keyBoardHeight = res.height
				if (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 H5
				this.footerHeight = this.$refs.footer.$el.offsetHeight
				this.height = this.pageHeight - this.footerHeight
				// #endif
				// #ifdef APP-PLUS
				uni.createSelectorQuery().in(this).select("#footer").boundingClientRect((data) => {
					this.footerHeight = data.height
					this.height = this.pageHeight - this.footerHeight
				}).exec()
				// #endif
			})
		},
		methods: {
			initListener() {
				uni.onKeyboardHeightChange(res => {
					let keyBoardHeight = res.height
					if (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"
		}
    }
    
}
  • 14
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
uniapp中,可以使用textarea组件来创建一个文本输入。根据引用和引用的代码示例,你可以在textarea组件中设置placeholder属性来显示输入的提示文本,并利用v-model属性来绑定一个变量来接收输入中的内容。这样,当用户在输入中输入内容时,绑定的变量将会自动更新。此外,你也可以设置maxlength属性来限制输入中的字符数。例如,你可以像这样创建一个textarea组件:```<textarea placeholder="请输入组织介绍" class="info-cell-text" maxlength="600" v-model="form.orgIntroduce"></textarea>```中的描述,可以使用textarea组件作为发送消息的输入。可以通过设置class属性来自定义输入的样式。此外,可以设置textarea自动增高的效果,使得输入随着内容的增多而逐渐增高。这样可以实现类似QQ输入的效果。总之,通过合理使用textarea组件的属性和样式,你可以在uniapp实现一个功能丰富的聊天界面。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [解决uniapp textarea标签快速输入时光标抖动或闪现的问题](https://blog.csdn.net/qq_46027468/article/details/128564512)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [uniapp 实现聊天页面 textarea固定底部高度自增](https://blog.csdn.net/six_teen/article/details/122509861)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值