微信小程序 仿微信聊天界面

news2024/11/18 7:27:35

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.inputValue
    if (!inputValue) {
      wx.showToast({
        title: '请输入聊天内容',
        icon: 'none'
      })
      return
    }
    this.setData({
      inputTemp: ""
    })
    var chatObj = {}
    chatObj.type = '1'
    chatObj.name = ''
    chatObj.msg = inputValue
    chatObj.time = that.getCurTime()
    chatObj.photoUrl = 'https://zhsq/icon_chat_photo_three.jpg'
    var chatList = that.data.chatList
    chatList.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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1413670.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024新版68套Axure RP大数据可视化大屏模板及通用组件+PSD源文件

Axure RP数据可视化大屏模板及通用组件库2024新版重新制作了这套新的数据可视化大屏模板及通用组件库V2版。新版本相比于V1版内容更加丰富和全面&#xff0c;但依然秉承“敏捷易用”的制作理念&#xff0c;这套作品也同样延续着我们对细节的完美追求&#xff0c;整个设计制作过…

uniapp安卓android离线打包本地打包整理

离线打包准备 下载Android studio 1.准备资源hbuilder 2.准备离线SDK 最新android平台SDK下载最新android平台SDK下载 3.离线打包key申请 4.直接导入HBuilder-Integrate-AS工程,直接运行simpleDemo项目即可 5.安装java 1.8 jdk-8u151-windows-x64 6.遇到这个报错报错Caus…

嵌入式软件工程师面试题——2025校招社招通用(C/C++)(四十一)

说明&#xff1a; 面试群&#xff0c;群号&#xff1a; 228447240面试题来源于网络书籍&#xff0c;公司题目以及博主原创或修改&#xff08;题目大部分来源于各种公司&#xff09;&#xff1b;文中很多题目&#xff0c;或许大家直接编译器写完&#xff0c;1分钟就出结果了。但…

防火墙在企业园区出口安全方案中的应用(ENSP实现)

拓扑图 需求&#xff1a; 1、企业出口网关设备必须具备较高的可靠性&#xff0c;为了避免单点故障&#xff0c;要求两台设备形成双机热备状态。当一台设备发生故障时&#xff0c;另一台设备会接替其工作&#xff0c;不会影响业务正常运行。 2、企业从两个ISP租用了两条链路&…

CSS3如何实现从右往左布局的按钮组(固定间距)

可以通过下方CSS实现&#xff0c;下面的CSS表示按钮从右往左布局&#xff0c;且间距为10px: .right-btn {position: relative;float: right;margin-right: 10px; }类似这种&#xff1a; 这种&#xff1a; 注意&#xff1a; 不能使用right:10px代替margin-right:10px&#x…

肌无力的判断方法有什么?

肌无力可能发病在身体的多个部位&#xff0c;最为显著的就是眼睑肌无力&#xff0c;那么除了这种明眼就可以看见的&#xff0c;那些不明显的又该怎么判断呢?看了你就知道了。 因为肌无力是一种比较常见的疾病,所以我们要了解全身肌肉无力的症状&#xff0c;下面为大家介绍肌无…

Python的hashlib模块:7种加密算法深入剖析

目录 一、引言 二、哈希算法简介 三、hashlib模块中的加密算法 MD5 SHA1 SHA224/SHA256/SHA384/SHA512 SHA3 其他算法&#xff1a; 四、加密算法比较与选择 五、实际应用与注意事项 六、总结 本文将深入探讨Python的hashlib模块&#xff0c;重点解析其中的七种加密算…

安全防御{第三次作业(在第二次作业上添加点需求)}

目录 需求&#xff1a; 拓扑图&#xff1a; 注意&#xff1a;先打开防火墙web界面&#xff0c;在此不做演示 1.要求一&#xff1a;&#xff0c;生产区在工作时间内可以访问服务器区&#xff0c;仅可以访问http服务器 2.要求二&#xff1a;办公区全天可以访问服务器区&#…

docker 构建应用

docker 应用程序开发手册 开发 docker 镜像 Dockerfile 非常容易定义镜像内容由一系列指令和参数构成的脚本文件每一条指令构建一层一个 Dockerfile 文件包含了构建镜像的一套完整指令指令不区分大小写&#xff0c;但是一般建议都是大写从头到尾按顺序执行指令必须以 FROM 指…

03 SB实战 -微头条之首页门户模块(跳转某页面自动展示所有信息+根据hid查询文章全文并用乐观锁修改阅读量)

1.1 自动展示所有信息 需求描述: 进入新闻首页portal/findAllType, 自动返回所有栏目名称和id 接口描述 url地址&#xff1a;portal/findAllTypes 请求方式&#xff1a;get 请求参数&#xff1a;无 响应数据&#xff1a; 成功 {"code":"200","mes…

苹果手机突然无服务了,这是怎么回事?

苹果手机无疑是一款备受青睐的智能设备&#xff0c;但有时候我们可能会面临一个令人困扰的情况——苹果手机突然无服务。这种情况可能会在任何时候发生&#xff0c;无论是在使用手机时&#xff0c;刚刚升级系统&#xff0c;或者是突然发现在本应有信号的区域却无法连接到运营商…

一种通过增强的面部边界实现精确面部表示的多级人脸超分辨率

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 摘要Abstract文献阅读&#xff1a;一种通过增强的面部边界实现精确面部表示的多级人脸超分辨率二、使用步骤1、研究背景2、方法提出3、相关方法3.1、FSR网络结构3.2…

【复现】Laykefu客服系统后台漏洞合集_29

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 2. 漏洞二&#xff1a; 3. 漏洞三&#xff1a; 4. 漏洞四&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 Laykefu客服系统是thinkphp5Gatewayworker搭建的web客服…

Springboot注解@Aspect(二)JoinPoint 使用详解

目录 JoinPoint 的作用 JoinPoint 常用方法 示例 JoinPoint 的子类和关联类 JoinPoint 的作用 在 Spring AOP 中&#xff0c;JoinPoint 接口代表了一个程序执行的点&#xff0c;比如方法执行或异常处理。当使用 AOP 通知&#xff08;Advice&#xff09;时&#xff0c;你可以…

笔记:VS C++ 使用NuGut包管理器下载和使用第三方库

1.打开NuGet包管理器。右键你的项目---->点击“管理NuGet程序包”。 2.根据关键字搜索第三方库&#xff0c;下载和安装。安装后会有绿色的“√”。 3.右键你的项目—>“生成依赖项”—>“生成自定义”&#xff0c;点击&#xff0c;将弹出下面的对话框。然后点击“查看…

Vulnhub靶场DC-3

本机192.168.223.128 靶机192.168.223.139 目标发现nmap -sP 192.168.223.0/24 端口扫描nmap -p- 192.168.223.139 之开启了一个80端口 看一下是什么服务 nmap -sV -p- -A 192.168.223.139是一个apache服务&#xff0c;joomla模板 看一下web 没什么有用信息。 扫描一下后台…

黑马程序员JavaWeb开发|Maven高级

一、分模块设计与开发 分模块设计&#xff1a; 将项目按照功能拆分成若干个子模块&#xff0c;方便项目的管理维护、扩展&#xff0c;也方便模块间的相互调用&#xff0c;资源共享。 注意&#xff1a;分模块开发需要先对模块功能进行设计&#xff0c;再进行编码。不会先将工…

Python基础(二十九、pymsql)

文章目录 一、安装pymysql库二、代码实践1.连接MySQL数据库2.创建表格3.插入数据4.查询数据5.更新数据6.删除数据 三、完整代码示例四、结论 使用Python的pymysql库可以实现数据存储&#xff0c;这是一种连接MySQL数据库的方式。在本篇文章中&#xff0c;将详细介绍如何使用pym…

muduo库的模拟实现——muduo库的介绍

文章目录 一、muduo库介绍二、背景知识1.epoll2.Reactor模式 三、功能模块划分1.工具部分2.Reactor部分3.TCPServer部分 一、muduo库介绍 muduo库是在Linux环境下使用C实现的一个多Reactor多线程的高性能网络服务器&#xff0c;作者陈硕&#xff0c;他还出了一本书《Linux多线…

leetcode:二叉树的中序遍历(外加先序,后序遍历)

题外&#xff1a;另外三种遍历可以看这&#xff1a; 层序遍历&#xff1a; Leetcode:二分搜索树层次遍历-CSDN博客 先序遍历&#xff1a; 二叉树的先序&#xff0c;中序&#xff0c;后序遍历-CSDN博客 后序遍历&#xff1a; 二叉树的先序&#xff0c;中序&#xff0c;后序…