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

news/2024/7/20 4:34:51 标签: 微信小程序, 微信, 小程序

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.niftyadmin.cn/n/5348755.html

相关文章

qt学习:HTTP接口+实战 请求网页图片显示

头文件 #include <QNetworkAccessManager> 网络管理者#include <QNetworkReply> 请求#include <QNetworkRequest> 响应 步骤 在pro里添加模块 QT core gui network 在ui界面的.h里加入头文件&#xff0c;并定义一个管理者指针&#xff0c;槽函数…

C# 只读文件删除提示失败,给文件修改属性

需求背景&#xff1a;处理文件后&#xff0c;删除源文件信息&#xff0c;但不能确保源文件是只读文件&#xff0c;因此需要修改文件属性 //设置文件属性 string path "文件路径"; File.SetAttributes(path, FileAttributes.Normal); //删除文件 File.Delete(path);参…

用ChatGPT写申请文书写进常春藤联盟?

一年前&#xff0c;ChatGPT 的发布引发了教育工作者的恐慌。现在&#xff0c;各大学正值大学申请季&#xff0c;担心学生会利用人工智能工具伪造入学论文。但是&#xff0c;聊天机器人创作的论文足以骗过大学招生顾问吗&#xff1f; ChatGPT简介 ChatGPT&#xff0c;全称聊天生…

Stable Diffusion插件Recolor实现黑白照片上色

今天跟大家分享一个使用Recolor插件通过SD实现老旧照片轻松变彩色&#xff0c;Recolor翻译过来的含义就是重上色&#xff0c;该模型可以保持图片的构图&#xff0c;它只会负责上色&#xff0c;图片不会发生任何变化。 一&#xff1a;插件下载地址 https://github.com/pkuliyi…

RocketMQ源码分析之消息重试(真相竟然是延时消息)

这里是weihubeats,觉得文章不错可以关注公众号小奏技术&#xff0c;文章首发。拒绝营销号&#xff0c;拒绝标题党 RocketMQ版本 5.1.0 普通消息 消息重试的的实现分并普通消息和顺序消息。两者的重试机制大同小异。我们这里先看看不同消息 这里是官网定义的消息重试次数以及…

网络安全全栈培训笔记(58-服务攻防-应用协议设备KibanaZabbix远控向日葵VNCTV)

第58天 服务攻防-应用协议&设备Kibana&Zabbix&远控向日葵&VNC&TV 知识点&#xff1a; 1、远程控制第三方应用安全 2、三方应用-向日葵&VNC&TV 3、设备平台-Zabbix&Kibanai漏洞 章节内容&#xff1a; 常见版务应用的安全测试&#xff1a; 1…

一步步安装Ruby攻略

在大多数操作系统上安装Ruby的步骤基本相同。以下是安装Ruby的详细步骤&#xff1a; 对于Ubuntu或其他基于Debian的系统&#xff1a; 打开终端。输入以下命令更新软件包列表&#xff1a; sql复制代码 sudo apt update 安装Ruby&#xff1a; 复制代码 sudo apt install rub…

机器学习的精髓-梯度下降算法

目 1. 梯度下降算法2. 梯度下降求解3. 总结 1. 梯度下降算法 梯度下降算法是一种优化算法&#xff0c;用于最小化函数的数值方法。它通过沿着函数梯度的反方向来更新参数&#xff0c;以逐步减小函数值。这一过程重复进行直到达到收敛条件。梯度下降算法有多种变体&#xff0c;…