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

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.mfbz.cn/a/350958.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FFMPEG解析ts流

三篇相关联的文章&#xff1a; ffmpeg下HLS解析过程-CSDN博客TS文件格式详解及解封装过程-CSDN博客 FFMPEG解析ts流-CSDN博客 一、简介 关于TS格式解析&#xff0c;可以参考《TS文件格式详解及解封装过程-CSDN博客》&#xff0c;本文主要代码部分解读。建议大家熟读iso138…

【JaveWeb教程】(30)SpringBootWeb案例之《智能学习辅助系统》的详细实现步骤与代码示例(3)员工管理的实现

目录 SpringBootWeb案例033. 员工管理3.1 分页查询3.1.1 基础分页3.1.1.1 需求分析3.1.1.2 接口文档3.1.1.3 思路分析3.1.1.4 功能开发3.1.1.5 功能测试3.1.1.6 前后端联调 3.1.2 分页插件3.1.2.1 介绍3.1.2.2 代码实现3.1.2.3 测试 3.2 分页查询(带条件)3.2.1 需求3.2.2 思路分…

电流检测电路设计方案汇总

电流检测电路设计方案&#xff08;一&#xff09; 低端检流电路的检流电阻串联到地&#xff08;图1&#xff09;&#xff0c;而高端检流电路的检流电阻是串联到高电压端&#xff08;图2&#xff09;。两种方法各有特点&#xff1a;低端检流方式在地线回路中增加了额外的线绕电…

内网穿透natapp使用教程(Linux)

我的使用场景&#xff1a;在家访问学校服务器&#xff0c;由于不在一个局域网&#xff0c;所以需要使用内网穿透&#xff0c;我使用的是natapp。需要在有局域网的时候做好以下步骤。 &#xff08;natapp官网&#xff1a;https://natapp.cn/&#xff09; 1. 下载客户端 &#x…

开发微信小程序,将图片下载到相册的方法,saveImageToPhotosAlbum怎么用

在开发微信小程序的时候&#xff0c;经常能看到小程序里面有下载按钮&#xff0c;如何将小程序中的图片下载到手机相册中那&#xff0c;下面给大家说一下怎么做&#xff0c;代码如何去写。 一、到微信小程序后台开启“用户隐私保护指引” 1.进入小程序后台&#xff0c;侧拉拉到…

第16章_网络编程(网络通信要素,TCP与UDP协议,网络编程API,TCP网络编程,UDP网络编程,URL编程)

文章目录 第16章_网络编程本章专题与脉络1. 网络编程概述1.1 软件架构1.2 网络基础 2. 网络通信要素2.1 如何实现网络中的主机互相通信2.2 通信要素一&#xff1a;IP地址和域名2.2.1 IP地址2.2.2 域名 2.3 通信要素二&#xff1a;端口号2.4 通信要素三&#xff1a;网络通信协议…

[C#]winform部署yolov5实例分割模型onnx

【官方框架地址】 https://github.com/ultralytics/yolov5 【算法介绍】 YOLOv5实例分割是目标检测算法的一个变种&#xff0c;主要用于识别和分割图像中的多个物体。它是在YOLOv5的基础上&#xff0c;通过添加一个实例分割模块来实现的。 在实例分割中&#xff0c;算法不仅…

自动化软件开发常用代码分享!

随着科技的发展&#xff0c;自动化软件开发已经成为现代企业不可或缺的一部分&#xff0c;自动化软件可以帮助企业提高生产效率、降低成本、优化业务流程。 而在自动化软件开发中&#xff0c;代码是实现这些功能的基础&#xff0c;本文将分享一些常用的自动化软件开发代码&…

苍穹外卖-前端部分(持续更新中)

d 第二种&#xff1a;cmd中输入 vue ui进入图形化界面选择npm,vue2进行创建 先将创建的Vue框架导入Vsocde开发工具 然后ctrshiftp 输入npm 点击serve将项目启动 下这种写法跨域会报错&#xff1a; 解决方法&#xff1a;

虚拟机内使用 archinstall 安装 arch linux 2024.01.01

文章目录 [toc]前言碎语安装 arch linuxArchinstall languageMirrorsLocalesDisk configurationBootloaderSwapHostnameRoot passwordUser accountProfileAudioKernelsAdditional packagesNetwork configurationTimezoneAutomatic time syncOptional repositoriesInstall 进入桌…

OceanMind海睿思入选《2023大数据产业年度创新技术突破奖》,并蝉联多项图谱

近日&#xff0c;由数据猿和上海大数据联盟主办&#xff0c;上海市经济和信息化委员会、上海市科学技术委员会指导的“第六届金猿季&魔方论坛——大数据产业发展论坛”在上海成功举行&#xff0c;吸引了数百位业界精英的参与。中新赛克海睿思作为国内数字化转型优秀厂商代表…

基于springboot+vue的校园资料分享平台(前后端分离)

博主主页&#xff1a;猫头鹰源码 博主简介&#xff1a;Java领域优质创作者、CSDN博客专家、公司架构师、全网粉丝5万、专注Java技术领域和毕业设计项目实战 主要内容&#xff1a;毕业设计(Javaweb项目|小程序等)、简历模板、学习资料、面试题库、技术咨询 文末联系获取 项目背景…

include文件包含

include 文件包含利用日志文件什么是日志文件 之所以会burp抓包上传就可以成功的原因&#xff0c;是因为burp可以绕过url编码&#xff0c;导致写入日志文件中的代码没有进行编码&#xff0c;可以直接解析成php文件 声明&#xff1a;其中图片并非本人实操&#xff0c;而是直接截…

软件包管理:在CentOS 7中部署Tengine

目录 下载&#xff1a; 方法一&#xff1a; 方法二&#xff1a; 部署&#xff1a; 实验操作 下载&#xff1a; 方法一&#xff1a; 1、打开浏览器搜索tengine并点击官网 2、选择需要安装的版本并复制链接链接 标题栏处可以更改为中文界面 下滑选择版本单击下载 在远程连…

matlab appdesigner系列-图窗3-菜单

菜单&#xff0c;常用来作为软件界面上方的菜单栏&#xff0c;可用来集成多种功能 示例&#xff1a;创建菜单栏的file选项&#xff0c;设置open&#xff0c;save&#xff0c;exit三个选项 操作步骤&#xff1a; 1&#xff09;将菜单、图像拖拽到画布上&#xff0c;并修改对应…

【Midjourney】绘画风格关键词

1.松散素描(Loose Sketch) "Loose sketch"&#xff08;松散素描&#xff09;通常指的是一种艺术或设计中的手绘风格&#xff0c;其特点是线条和形状的表现相对宽松、自由&#xff0c;没有过多的细节和精确度。这样的素描通常用于表达创意、捕捉概念或者作为设计的初步…

《WebKit 技术内幕》学习之十五(5):Web前端的未来

5 Crosswalk项目 Crosswalk项目是由英特尔公司发起的一个开源项目&#xff0c;该项目基于WebKit&#xff08;Blink&#xff09;和Chromium等开源项目打造&#xff0c;其目的是提供一个跨不同操作系统的Web运行环境&#xff0c;包括Android、Tizen、Linux、Windows、MacOS等众多…

Docker容器(自定义镜像,Dockerfile,网桥,DockerCompose)

自定义镜像 镜像就是包含了应用程序、程序运行的系统函数库、运行配置等文件的文件包。构建镜像的过程其实就是把上述文件打包的过程。 构建步骤 镜像结构 Dockerfile 它是一个文本文件&#xff0c;包含很多指令&#xff0c;用指令来说明要执行什么操作来构建镜像。 官网&am…

滴滴开源小程序框架 Mpx 新特性:局部运行时能力增强

Mpx 是滴滴开源的一款增强型跨端小程序框架&#xff0c;自 2018 年立项开源以来如今已经进入第六个年头&#xff0c;在这六年间&#xff0c;Mpx 根植于业务&#xff0c;与业务共同成长&#xff0c;针对小程序业务开发中遇到的各类痛点问题提出了解决方案&#xff0c;并在滴滴内…

LlamaIndex和LangChain谁更胜一筹?

▼最近直播超级多&#xff0c;预约保你有收获 今晚直播&#xff1a;《LlamaIndex构建应用案例实战》 —1— LlamaIndex OR LangChain&#xff1f; LangChain 和 LlamaIndex 都是 AGI 时代新的应用程序开发框架&#xff0c;到底有什么区别&#xff1f; 第一、LangChain 是一个围…
最新文章