微信小程序 仿微信聊天界面
1. 需求效果图

2. 方案
为实现这样的效果,首先要解决两个问题:
2.1.点击输入框弹出软键盘后,将已有的少许聊天内容弹出,导致看不到的问题
点击输入框弹出软键盘后,将已有的少许聊天内容弹出,导致看不到的问题。
(1)首先我们需要将input的自动向上推给关掉,这里有个坑:
在input组件中添加:adjust-position=‘{{false}}’,而不是:adjust-position=‘false’。
这么做虽然不再向上推,但却导致了软键盘弹起时,会遮挡屏幕下部分的消息。
(2)如何解决软键盘弹起时,会遮挡屏幕下部分的消息?
当软键盘弹起时,将scroll-view的高度缩短至软键盘遮挡不到的屏幕上方部分,当软键盘收起时,再将scroll-view的高度还原,这样解决了遮挡问题。
提示:
input中的bindfocus='focus’可获取软键盘高度并监听软键盘弹起,bindblur='blur’可监听软键盘收起,var windowHeight = wx.getSystemInfoSync().windowHeight;可获得屏幕高度。
scrollHeight(滚动条高度) = windowHeight(屏幕高度) - 软键盘高度;
最后将input组件放在软键盘上面就完成了。
2.2.键盘弹出或收起时,聊天消息没有自动滚到最底部
首先解决第二个问题,自动滚动到最底部,这很简单,这里提供三种方法(推荐第三种):
(1)计算每条消息的最大高度,设置scroll-top=(单条msg最大高度 * msg条数)px。
(2)用 将展示msg的目标scroll-view包裹,
通过js获取到该view的实际高度:
var that = this;
var query = wx.createSelectorQuery();
query.select('.scrollMsg').boundingClientRect(function(rect) {that.setData({scrollTop: rect.height+'px';});
}).exec();
(3)(推荐)将所有msg都编号如:msg-0,msg-1,msg-2… 直接锁定最后一条msg,滚动到那里。
在scroll-view中添加:scroll-into-view=‘{{toView}}’,
在wx:for后面添加:wx:for-index=“index”,
在每个msg布局中添加:id=‘msg-{{index}}’,
this.setData({toView: 'msg-' + (msgList.length - 1)
})
3. 代码
3.1.gridGroup.wxml
<view class="page-layout"><view class="page-body" id="x_chat"><view wx:key="{{index}}" wx:for="{{chatList}}"><view class="chat-item-body"><view class="chat-item-time">{{item.time}}</view><view wx:key="{{index}}" wx:if="{{item.type == '0'}}" class="chat-item-layout chat-left"><view class="chat-inner-layout"><view class="chat-item-name">{{item.name}}</view><view class="chat-item-msg-layout"><image class="chat-item-photo" bindtap="scanClick" src="{{item.photoUrl}}" mode="aspectFit"></image><view class="chat-inner-msg-left">{{item.msg}}</view></view></view></view></view><view wx:key="{{index}}" wx:if="{{item.type == '1'}}" class="chat-item-layout chat-right"><view class="chat-inner-layout"><view class="chat-item-name-right">{{item.name}}</view><view class="chat-item-msg-layout"><view class="chat-inner-msg-right">{{item.msg}} </view><image class="chat-item-photo" bindtap="scanClick" src="{{item.photoUrl}}" mode="aspectFit"></image></view></view></view></view></view><view class="submit-layout"><input class="submit-input" placeholder="点击输入,开始聊天吧" value="{{inputTemp}}" bindinput="bindKeyInput" /><view class="submit-submit" type="submit" size="mini" bindtap="submitTo">发送</view></view>
</view>
3.2.gridGroup.wxss
.page-layout {width: 100%;height: 100%;box-sizing: border-box;
}.page-body {width: 100%;display: flex;flex-direction: column;padding-bottom: 56px;
}.chat-item-body {display: flex;flex-direction: column;margin-top: 20rpx;
}.chat-item-time {width: 100vw;text-align: center;font-size: 28rpx;color: #ccc;border-radius: 10rpx;margin-top: 40rpx;
}.chat-item-layout {display: block;max-width: 82%;margin: 1rpx 5rpx;box-sizing: border-box;padding: 0 1rpx;
}.chat-right {float: right;
}.chat-left {float: left;
}.chat-inner-layout {display: flex;flex-direction: column;
}.chat-item-photo {width: 70rpx;height: 70rpx;min-width: 70rpx;min-height: 70rpx;border-radius: 50%;
}.chat-item-msg-layout {display: flex;flex-direction: row;
}.chat-item-name {display: flex;flex-direction: row;align-items: center;font-size: 28rpx;color: #999;border-radius: 10rpx;margin: 5rpx 0 0 80rpx;
}.chat-item-name-right {display: flex;flex-direction: row;align-items: center;font-size: 28rpx;color: #999;border-radius: 10rpx;margin: 5rpx 0 0 5rpx;
}.chat-inner-msg-left {display: inline-block;flex-direction: row;align-items: center;color: #000;font-size: 30rpx;border-radius: 10rpx;background: white;padding: 15rpx 5rpx 15rpx 15rpx;margin-left: 12rpx;
}.chat-inner-msg-right {display: inline-block;color: #000;font-size: 30rpx;border-radius: 10rpx;background: #87EE5F;padding: 15rpx 5rpx 15rpx 15rpx;margin-right: 12rpx;
}.submit-layout {position: absolute;bottom: 0;width: 100%;background: #eee;flex-direction: row;
}.submit-layout {width: 100%;position: fixed;bottom: 0;border-top: 1px solid #ddd;padding: 10rpx 0;display: flex;flex-direction: row;align-items: center;
}.submit-input {flex: 1;background: #fff;margin: 5rpx 10rpx;border-radius: 5rpx;padding: 15rpx 20rpx;color: #333;font-size: 30rpx;
}.submit-submit {background-color: #13c25f;color: #333;font-weight: 700;font-size: 30rpx;border-radius: 10rpx;padding: 18rpx 30rpx;margin-right: 10rpx;
}
3.3.gridGroup.js
import tinyCommunityJson from '../../public/json/tinyCommunityJson';
Page({data: {inputValue: '',chatList: tinyCommunityJson.data.rows,},onLoad: function (options) {var title = options.title// 设置标题wx.setNavigationBarTitle({title: title,})//滚动到页面底部that.pageScrollToBottom()},/*** 输入监听*/bindKeyInput: function (e) {this.setData({inputValue: e.detail.value})},/*** 发送*/submitTo: function (e) {var that = this;var inputValue = that.data.inputValueif (!inputValue) {wx.showToast({title: '请输入聊天内容',icon: 'none'})return}this.setData({inputTemp: ""})var chatObj = {}chatObj.type = '1'chatObj.name = ''chatObj.msg = inputValuechatObj.time = that.getCurTime()chatObj.photoUrl = 'https://zhsq/icon_chat_photo_three.jpg'var chatList = that.data.chatListchatList.push(chatObj);that.setData({chatList: chatList})//滚动到页面底部that.pageScrollToBottom()},/*** 获取当前时间*/getCurTime() {var date = new Date()var y = date.getFullYear();var m = date.getMonth() + 1;m = m < 10 ? ('0' + m) : m;var d = date.getDate();d = d < 10 ? ('0' + d) : d;var h = date.getHours();h = h < 10 ? ('0' + h) : h;var minute = date.getMinutes();minute = minute < 10 ? ('0' + minute) : minute;var second = date.getSeconds();second = second < 10 ? ('0' + second) : second;return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;},/*** 滚动到页面底部*/pageScrollToBottom: function () {let that = this;wx.createSelectorQuery().select('#x_chat').boundingClientRect(function (rect) {let top = rect.height * that.data.chatList.length;wx.pageScrollTo({scrollTop: top,duration: 100})}).exec()},
})
3.4.tinyCommunityJson.js
const data = {rows: [{type: '0',name: '群主',msg: '大家好,欢迎进入微社区群,如有问题可在群里聊天询问',time: '2024-01-26 13:43:12',photoUrl: 'https://zhsq/icon_chat_photo_two.jpg',},{type: '0',name: '小助手',msg: '2024微报事、微呼应活动正在进行中,希望大家踊跃参加。',time: '2024-01-26 13:43:15',photoUrl: 'https://zhsq/icon_service.png',},{type: '1',name: '',msg: '已参加微呼应活动',time: '2024-01-26 13:56:10',photoUrl: 'https://zhsq/icon_chat_photo_three.jpg',},{type: '0',name: '第五网格员',msg: '已参加微报事活动',time: '2024-01-26 13:59:12',photoUrl: 'https://zhsq/icon_chat_photo_one.jpg',},
],
};
module.exports = {data: data,
}
4. 优化
聊天框三角形的制作和使用

4.1. gridChat.wxml
<view><!-- 右侧布局 --><view class="right-layout"><view class='right-msg'>我是右侧布局我是右侧布局我是右侧布局我是右侧布局我是右侧布局</view><view class="right-arrow-layout"><image class="right-arrow-img" src='https://zhsq/icon_arrow_right_green.png' mode='widthFix'></image></view><image class="right-arrow-photo" src='https://zhsq/icon_chat_photo_one.jpg' mode='aspectFill'></image></view><!-- 左侧布局 --><view class="left-layout"><image class="left-arrow-photo" src='https://zhsq/icon_chat_photo_two.jpg' mode='aspectFill'></image><view class="left-arrow-layout"><image class="left-arrow-img" src='https://zhsq/icon_arrow_left_white.png' mode='widthFix'></image></view><view class='left-msg'>我是左侧布局</view></view>
</view>
4.2. gridChat.wxss
page {background-color: #eee;
}
/* 左侧布局 */
.left-layout {display: flex;justify-content: flex-start;padding: 20rpx 60rpx 2vw 2vw;
}.left-arrow-photo {width: 60rpx;height: 60rpx;min-width: 60rpx;min-height:60rpx ;border-radius: 50%;margin-top: 5rpx;
}.left-msg {font-size: 32rpx;color: #444;line-height: 45rpx;padding: 10rpx 20rpx 10rpx 5rpx;background-color: white;margin-left: -12rpx;border-radius: 10rpx;z-index: 10;
}.left-arrow-layout {width: 35rpx;height: 65rpx;display: flex;align-items: center;z-index: 9;
}.left-arrow-img {width: 35rpx;
}/* 右侧布局 */
.right-layout {display: flex;justify-content: flex-end;padding: 20rpx 2vw 2vw 15vw;
}
.right-arrow-photo {width: 60rpx;height: 60rpx;min-width: 60rpx;min-height:60rpx ;border-radius: 50%;margin-top: 5rpx;
}
.right-msg {font-size: 32rpx;color: #444;line-height: 45rpx;padding: 10rpx 5rpx 10rpx 20rpx;background-color: #96EB6A;margin-right: -12rpx;border-radius: 10rpx;z-index: 10;
}.right-arrow-layout {width: 35rpx;height: 65rpx;margin-right: 5rpx;display: flex;align-items: center;z-index: 9;
}.right-arrow-img {width: 35rpx;
}
相关文章:
微信小程序 仿微信聊天界面
1. 需求效果图 2. 方案 为实现这样的效果,首先要解决两个问题: 2.1.点击输入框弹出软键盘后,将已有的少许聊天内容弹出,导致看不到的问题 点击输入框弹出软键盘后,将已有的少许聊天内容弹出,导致看不到的问…...
中国社会科学院大学-新加坡社科大学 招生简章
Singapore University of Social Sciences--University of Chinese Academy of Social Sciences Doctor of Business Administration (DBA) Programme in Global Strategy and Leadership 一、项目简介 全球经济正在经历由科技进步和创新、政治和人口剧烈变化所带来的巨大的不…...
js中继承的详解(一文读懂)
文章目录 一、是什么二、实现方式原型链继承构造函数继承组合继承原型式继承寄生式继承寄生组合式继承 三、总结参考文献 一、是什么 继承(inheritance)是面向对象软件技术当中的一个概念。 如果一个类别B“继承自”另一个类别A,就把这个B称…...
Android studio使用svg矢量图
https://www.iconfont.cn/ https://www.jyshare.com/more/svgeditor/ https://editor.method.ac/ https://inloop.github.io/svg2android/ Pattern Monster - SVG 图案生成器 Android studio使用svg矢量图自适应不同的分辨率, svg矢量图绘制以及转换为And…...
《Access Path Selectionin a Relational Database Management System》论文笔记
以下是根据论文归纳出的一些查询优化器公式和知识点,有没有用不知道,先码起来。 SQL执行优化过程 处理SQL语句是从解析用户输入的SQL语句开始,经过一系列优化过程,最终生成机器代码并执行的过程。这个过程涉及到多个复杂的步骤&…...
【AI_Design】Midjourney学习笔记
目录 后缀解析Promot合格使用prompt关键词描述 关键词化合作用关键词网站推荐 联合Chatgpt使用总结 后缀解析 –ar:宽高比设置–c:多样性设置(数值0-100,默认值0)–s:风格化设置(数值0-1000&am…...
面试宝典之深谈JVM
面试宝典之深谈JVM 1.为什么需要JVM,不要JVM可以吗? 1.JVM可以帮助我们屏蔽底层的操作系统 一次编译,到处运行 2.JVM可以运行Class文件 2.JDK,JRE以及JVM的关系 3.我们的编译器到底干了什么事? 仅仅是将我们的 .ja…...
idea配置tomcat
推荐链接:IntelliJ IDEA中配置Tomcat(超详细)_idea怎么配置tomcat服务器-CSDN博客 1,官员下载链接:Apache Tomcat - Welcome! 附本人下载的 tomcat9 的百度网盘链接 链接:https://pan.baidu.com/s/1DpyBGnG4mUGTm5Z…...
【MyBatis】操作数据库——入门
文章目录 为什么要学习MyBatis什么是MyBatisMyBatis 入门创建带有MyBatis框架的SpringBoot项目数据准备在配置文件中配置数据库相关信息实现持久层代码单元测试 为什么要学习MyBatis 前面我们肯定多多少少学过 sql 语言,sql 语言是一种操作数据库的一类语言&#x…...
免费分享一套SpringBoot+Vue药店(药房)管理系统,帅呆了~~
大家好,我是java1234_小锋老师,看到一个不错的SpringBootVue药店(药房)管理系统 ,分享下哈。 项目视频演示 【免费】SpringBootVue药店(药房)管理系统 Java毕业设计_哔哩哔哩_bilibili【免费】SpringBootVue药店(药房)管理系统 Java毕业设计…...
视频怎么加水印?分享两个简单的加水印的方法
在数字媒体时代,视频已经成为信息传播的重要方式。许多人在创作视频是会加上自己独特的水印,防止视频被盗用。水印作为数字版权保护技术的一种,可以有效地防止视频被非法复制、传播或篡改,从而保护创作者的权益和利益。下面我分享…...
Apache Commons Collection3.2.1反序列化分析(CC1)
Commons Collections简介 Commons Collections是Apache软件基金会的一个开源项目,它提供了一组可复用的数据结构和算法的实现,旨在扩展和增强Java集合框架,以便更好地满足不同类型应用的需求。该项目包含了多种不同类型的集合类、迭代器、队…...
MySQL入门篇(10)-聚合函数的应用
MySQL数据库聚合函数的应用 在MySQL数据库中,聚合函数用于计算一组数据的统计值并返回结果。这些函数可以应用于查询语句中,对数据进行汇总、计数、平均值计算等操作。本文将介绍一些常用的MySQL聚合函数及其应用。 1. COUNT函数 COUNT函数用于计算指…...
Vue3基本概念
script部分 export default对象的属性: name:组件的名称 components:存储中用到的所有组件 props:存储父组件传递给子组件的数据 watch():当某个数据发生变化时触发 computed:动态计算某个数据 setup(pro…...
每日OJ题_算法_模拟①_力扣1576. 替换所有的问号
目录 模拟算法原理 力扣1576. 替换所有的问号 解析代码 模拟算法原理 模拟算法是一种常用的计算机算法,它模拟了实际问题的运行过程,并通过数学模型来预测结果。模拟算法可以应用于各个领域,例如物理、化学、生物、计算机网络等等。 模拟算…...
杂题——试题 算法训练 区间最大和
分析: 如果使用两个for循环遍历所有情况,运行会超时解决运行超时的关键点在于:及时停止累加,丢弃当前的子序列 比如【1,-2,3,10】从第一个数字开始的子序列的和小于从第三个数字开始的子序列的和…...
(安卓)跳转应用市场APP详情页的方式
前言 最近在做一个需求,需要从自己APP进入到系统的应用市场 方便用户在应用市场给自己的APP打分 于是查阅了一些资料,下面说一下实现方法 实现方案 一般来说,最简单的方案就是这样: val uri Uri.parse("market://details…...
亚信安全助力宁夏首个人工智能数据中心建成 铺设绿色算力安全底座
近日,由宁夏西云算力科技有限公司倾力打造,亚信安全科技股份有限公司(股票代码:688225)全力支撑,总投资达数十亿元人民币的宁夏智算中心项目,其一期工程——宁夏首个采用全自然风冷技术的30KW机…...
ASP.NET Core WebAPI_解决跨域问题(前端后端)
说明 我的前端框架为Vue3 前后端跨域选其一即可 前端跨域 在项目的根目录找到vite.config.js文件,添加代码: server: {proxy: {/api: {target: https://localhost:xxxx,changeOrigin: true,secure: false},},} axios代码片段: …...
保姆级的指针详解(超详细)
目录 一.内存和地址 1.初识指针 2.如何理解编址 二. 指针变量 三.指针的解引用操作符 1.指针变量的大小 四.指针变量类型的意义 五.指针的运算 1.指针加减整数 2.指针减指针 3.野指针 3.1指针未初始化 3.2指针越界访问 3.3指针指向的空间被提前释放 3.4如何规…...
挑战杯推荐项目
“人工智能”创意赛 - 智能艺术创作助手:借助大模型技术,开发能根据用户输入的主题、风格等要求,生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用,帮助艺术家和创意爱好者激发创意、提高创作效率。 - 个性化梦境…...
Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分
一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计,提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合:各模块职责清晰,便于独立开发…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
探索Selenium:自动化测试的神奇钥匙
目录 一、Selenium 是什么1.1 定义与概念1.2 发展历程1.3 功能概述 二、Selenium 工作原理剖析2.1 架构组成2.2 工作流程2.3 通信机制 三、Selenium 的优势3.1 跨浏览器与平台支持3.2 丰富的语言支持3.3 强大的社区支持 四、Selenium 的应用场景4.1 Web 应用自动化测试4.2 数据…...
