详解微信小程序实现仿微信聊天界面(各种细节处理)


Posted in Javascript onFebruary 17, 2019

本文介绍了微信小程序实现仿微信聊天界面,分享给大家,具体如下:

下面先来看看效果

详解微信小程序实现仿微信聊天界面(各种细节处理)

为实现这样的效果,首先要解决两个问题:

1.点击输入框弹出软键盘后,将已有的少许聊天内容弹出,导致看不到的问题;

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)
})

到这里第二个问题解决了,那么我们回过来解决第一个问题:

(点击输入框弹出软键盘后,将已有的少许聊天内容弹出,导致看不到的问题)

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组件放在软键盘上面就完成了。

各位要不要代码?

contact.js:

// pages/contact/contact.js
const app = getApp();
var inputVal = '';
var msgList = [];
var windowWidth = wx.getSystemInfoSync().windowWidth;
var windowHeight = wx.getSystemInfoSync().windowHeight;
var keyHeight = 0;

/**
 * 初始化数据
 */
function initData(that) {
 inputVal = '';

 msgList = [{
   speaker: 'server',
   contentType: 'text',
   content: '欢迎来到英雄联盟,敌军还有30秒到达战场,请做好准备!'
  },
  {
   speaker: 'customer',
   contentType: 'text',
   content: '我怕是走错片场了...'
  }
 ]
 that.setData({
  msgList,
  inputVal
 })
}

/**
 * 计算msg总高度
 */
// function calScrollHeight(that, keyHeight) {
//  var query = wx.createSelectorQuery();
//  query.select('.scrollMsg').boundingClientRect(function(rect) {
//  }).exec();
// }

Page({

 /**
  * 页面的初始数据
  */
 data: {
  scrollHeight: '100vh',
  inputBottom: 0
 },

 /**
  * 生命周期函数--监听页面加载
  */
 onLoad: function(options) {
  initData(this);
  this.setData({
   cusHeadIcon: app.globalData.userInfo.avatarUrl,
  });
 },

 /**
  * 生命周期函数--监听页面显示
  */
 onShow: function() {

 },

 /**
  * 页面相关事件处理函数--监听用户下拉动作
  */
 onPullDownRefresh: function() {

 },

 /**
  * 页面上拉触底事件的处理函数
  */
 onReachBottom: function() {

 },

 /**
  * 获取聚焦
  */
 focus: function(e) {
  keyHeight = e.detail.height;
  this.setData({
   scrollHeight: (windowHeight - keyHeight) + 'px'
  });
  this.setData({
   toView: 'msg-' + (msgList.length - 1),
   inputBottom: keyHeight + 'px'
  })
  //计算msg高度
  // calScrollHeight(this, keyHeight);

 },

 //失去聚焦(软键盘消失)
 blur: function(e) {
  this.setData({
   scrollHeight: '100vh',
   inputBottom: 0
  })
  this.setData({
   toView: 'msg-' + (msgList.length - 1)
  })

 },

 /**
  * 发送点击监听
  */
 sendClick: function(e) {
  msgList.push({
   speaker: 'customer',
   contentType: 'text',
   content: e.detail.value
  })
  inputVal = '';
  this.setData({
   msgList,
   inputVal
  });


 },

 /**
  * 退回上一页
  */
 toBackClick: function() {
  wx.navigateBack({})
 }

})

contact.wxml:

<!--pages/contact/contact.wxml-->

<view>

 <scroll-view scroll-y scroll-into-view='{{toView}}' style='height: {{scrollHeight}};'>
  <!-- <view class='scrollMsg'> -->
  <block wx:key wx:for='{{msgList}}' wx:for-index="index">

   <!-- 单个消息1 客服发出(左) -->
   <view wx:if='{{item.speaker=="server"}}' id='msg-{{index}}' style='display: flex; padding: 2vw 11vw 2vw 2vw;'>
    <view style='width: 11vw; height: 11vw;'>
     <image style='width: 11vw; height: 11vw; border-radius: 10rpx;' src='../../images/contact_member.png'></image>
    </view>
    <view style='width: 4vw; height: 11vw; margin-left: 0.5vw; display: flex; align-items: center; z-index: 9;'>
     <image style='width: 4vw;' src='../../images/left_msg.png' mode='widthFix'></image>
    </view>
    <view class='leftMsg'>{{item.content}}</view>
   </view>

   <!-- 单个消息2 用户发出(右) -->
   <view wx:else id='msg-{{index}}' style='display: flex; justify-content: flex-end; padding: 2vw 2vw 2vw 11vw;'>
    <view class='rightMsg'>{{item.content}}</view>
    <view style='width: 4vw; height: 11vw; margin-right: 0.5vw; display: flex; align-items: center; z-index: 9;'>
     <image style='width: 4vw;' src='../../images/right_msg.png' mode='widthFix'></image>
    </view>
    <view style='width: 11vw; height: 11vw;'>
     <image style='width: 11vw; height: 11vw; border-radius: 10rpx;' src='{{cusHeadIcon}}'></image>
    </view>
   </view>

  </block>
  <!-- </view> -->

  <!-- 占位 -->
  <view style='width: 100%; height: 18vw;'></view>
 </scroll-view>

 <view class='inputRoom' style='bottom: {{inputBottom}}'>
  <image style='width: 7vw; margin-left: 3.2vw;' src='../../images/pic_icon.png' mode='widthFix'></image>
  <input bindconfirm='sendClick' adjust-position='{{false}}' value='{{inputVal}}' confirm-type='send' bindfocus='focus' bindblur='blur'></input>
 </view>
</view>

contact.wxss:

/* pages/contact/contact.wxss */

page {
 background-color: #f1f1f1;
}

.inputRoom {
 width: 100vw;
 height: 16vw;
 border-top: 1px solid #cdcdcd;
 background-color: #f1f1f1;
 position: fixed;
 bottom: 0;
 display: flex;
 align-items: center;
 z-index: 20;
}

input {
 width: 76vw;
 height: 9.33vw;
 background-color: #fff;
 border-radius: 40rpx;
 margin-left: 2vw;
 padding: 0 3vw;
 font-size: 28rpx;
 color: #444;
}

.leftMsg {
 font-size: 35rpx;
 color: #444;
 line-height: 7vw;
 padding: 2vw 2.5vw;
 background-color: #fff;
 margin-left: -1.6vw;
 border-radius: 10rpx;
 z-index: 10;
}

.rightMsg {
 font-size: 35rpx;
 color: #444;
 line-height: 7vw;
 padding: 2vw 2.5vw;
 background-color: #96EB6A;
 margin-right: -1.6vw;
 border-radius: 10rpx;
 z-index: 10;
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
把字符串按照特定的字母顺序进行排序的js代码
Jan 28 Javascript
sliderToggle在写jquery的计时器setTimeouter中不生效
May 26 Javascript
window.open()详解及浏览器兼容性问题示例探讨
May 29 Javascript
jquery mobile页面跳转后样式丢失js失效的解决方法
Sep 06 Javascript
jQuery中document与window以及load与ready 区别详解
Dec 29 Javascript
一道JS前端闭包面试题解析
Dec 25 Javascript
JS两个数组比较,删除重复值的巧妙方法(推荐)
Jun 03 Javascript
微信小程序获取用户信息的两种方法wx.getUserInfo与open-data实例分析
May 03 Javascript
如何将Node.js中的回调转换为Promise
Nov 10 Javascript
JavaScript实现京东快递单号查询
Nov 30 Javascript
Javascript 模拟mvc实现点餐程序案例详解
Dec 24 Javascript
linux服务器快速卸载安装node环境(简单上手)
Feb 22 Javascript
JavaScript遍历DOM元素的常见方式示例
Feb 16 #Javascript
原生JS实现逼真的图片3D旋转效果详解
Feb 16 #Javascript
JS实现简单的抽奖转盘效果示例
Feb 16 #Javascript
mocha的时序规则讲解
Feb 16 #Javascript
jQuery实现ajax的嵌套请求案例分析
Feb 16 #jQuery
解决微信小程序中转换时间格式IOS不兼容的问题
Feb 15 #Javascript
详解Element 指令clickoutside源码分析
Feb 15 #Javascript
You might like
虫族 ZERG 概述
2020/03/14 星际争霸
PHP实现根据设备类型自动跳转相应页面的方法
2014/07/24 PHP
PHP获取指定时间段之间的 年,月,天,时,分,秒
2016/06/05 PHP
php安装扩展mysqli的实现步骤及报错解决办法
2017/09/23 PHP
js变量作用域及可访问性的探讨
2006/11/23 Javascript
js实现缓冲运动效果的方法
2015/04/10 Javascript
javascript动态设置样式style实例分析
2015/05/13 Javascript
详解JavaScript中setSeconds()方法的使用
2015/06/11 Javascript
jQuery实现平滑滚动页面到指定锚点链接的方法
2015/07/15 Javascript
JS禁止查看网页源代码的实现方法
2016/10/12 Javascript
Node.js读取文件内容示例
2017/03/07 Javascript
详解vue项目构建与实战
2017/06/27 Javascript
Vue 全局loading组件实例详解
2018/05/29 Javascript
利用vue.js把静态json绑定bootstrap的table方法
2018/08/28 Javascript
Vue.js的复用组件开发流程完整记录
2018/11/29 Javascript
JavaScript寄生组合式继承原理与用法分析
2019/01/11 Javascript
[10:34]DOTA2上海特级锦标赛全纪录
2016/03/25 DOTA
python基于multiprocessing的多进程创建方法
2015/06/04 Python
基于Python __dict__与dir()的区别详解
2017/10/30 Python
详解Python Matplot中文显示完美解决方案
2019/03/07 Python
python Django编写接口并用Jmeter测试的方法
2019/07/31 Python
Python中使用gflags实例及原理解析
2019/12/13 Python
Tensorflow实现多GPU并行方式
2020/02/03 Python
Python猜数字算法题详解
2020/03/01 Python
python 实现朴素贝叶斯算法的示例
2020/09/30 Python
python 实现网易邮箱邮件阅读和删除的辅助小脚本
2021/03/01 Python
美国专注于健康商品的网站:eVitamins
2017/01/23 全球购物
Anthropologie英国:美国家喻户晓的休闲服装和家居产品品牌
2018/12/05 全球购物
会计专业毕业生自我评价
2013/09/25 职场文书
学生干部的自我评价分享
2014/01/18 职场文书
企业办公室岗位职责
2014/03/12 职场文书
学校端午节活动总结
2015/02/11 职场文书
医学生自荐信范文
2015/03/05 职场文书
银行优秀员工推荐信
2015/03/24 职场文书
酒店宣传语大全
2015/07/13 职场文书
win11如何查看端口是否被占用? Win11查看端口是否占用的技巧
2022/04/05 数码科技