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

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;
}
相关推荐
尘浮生3 小时前
Java项目实战II基于微信小程序的电影院买票选座系统(开发文档+数据库+源码)
java·开发语言·数据库·微信小程序·小程序·maven·intellij-idea
HerayChen6 小时前
微信小程序混合 h5 wx.miniProgram是 undefined
微信小程序·小程序·h5
耶啵奶膘10 小时前
uniapp+vue2全局监听退出小程序清除缓存
小程序·uni-app
中云DDoS CC防护蔡蔡12 小时前
微信小程序被攻击怎么选择高防产品
服务器·网络安全·微信小程序·小程序·ddos
井眼16 小时前
微信小程序-prettier 格式化
微信小程序·小程序
qq_174482857518 小时前
springboot基于微信小程序的旧衣回收系统的设计与实现
spring boot·后端·微信小程序
wqq_99225027718 小时前
springboot基于微信小程序的食堂预约点餐系统
数据库·微信小程序·小程序
licy__1 天前
微信小程序登录注册页面设计(小程序项目)
微信小程序·小程序
wqq_9922502771 天前
springboot基于微信小程序的农产品交易平台
spring boot·后端·微信小程序
说私域2 天前
基于“开源 2+1 链动模式 S2B2C 商城小程序”的社区团购运作主体特征分析
大数据·人工智能·小程序