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

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的实际高度:

javascript 复制代码
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}}',

javascript 复制代码
this.setData({
	toView: 'msg-' + (msgList.length - 1)
})

3. 代码

3.1.gridGroup.wxml

javascript 复制代码
<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

javascript 复制代码
.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

javascript 复制代码
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

javascript 复制代码
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

javascript 复制代码
<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

javascript 复制代码
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;
}
相关推荐
chaosama1 小时前
禁止uni小程序ios端上下拉伸(橡皮筋效果)
ios·小程序
瑶琴AI前端2 小时前
uniapp实现H5和微信小程序获取当前位置(腾讯地图)
微信小程序·小程序·uni-app
丁总学Java7 小时前
页面、组件、应用、生命周期(微信小程序)
微信小程序·小程序·生命周期
编程千纸鹤11 小时前
高校宿舍信息管理系统小程序
小程序·宿舍管理小程序
说私域12 小时前
基于开源 AI 智能名片 S2B2C 商城小程序的视频号交易小程序优化研究
人工智能·小程序·零售
Rainbow_Technology16 小时前
劫持微信聊天记录并分析还原 —— 数据库结构讲解(四)
微信·微信聊天记录查看·微信聊天记录破解
丁总学Java1 天前
微信小程序,点击bindtap事件后,没有跳转到详情页,有可能是app.json中没有正确配置页面路径
微信小程序·小程序·json
说私域1 天前
基于开源 AI 智能名片、S2B2C 商城小程序的用户获取成本优化分析
人工智能·小程序
mosen8681 天前
Uniapp去除顶部导航栏-小程序、H5、APP适用
vue.js·微信小程序·小程序·uni-app·uniapp
qq22951165021 天前
微信小程序的汽车维修预约管理系统
微信小程序·小程序·汽车