• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >swift > Swift 3.1聊天界面键盘效果的实现详解

Swift 3.1聊天界面键盘效果的实现详解

作者:Murray66 字体:[增加 减小] 来源:互联网 时间:2017-05-28

Murray66 通过本文主要向大家介绍了swift 界面,taylor swift,swift,swift code是什么意思,swift bic等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

前言

最近写的 Swift 项目里要实现一个聊天界面,在处理键盘弹出的时候遇到了一点麻烦。

麻烦就在于键盘弹出后如何处理屏幕和键盘的关系

经过一番死磕,终于做出了想要的效果,效果如下:

注:原本项目是 Swift 2.3 写的,为了写这篇博客,用 Swift 3.1 重新实现了一遍。

感受:方法名真的缩短了不少,😁


分析

现在开始,就让我来分析一下这次死磕历程。

一开始想到了两种处理方法,一种是 键盘弹出消失的同时,输入栏随着键盘移动,一种是 键盘弹出消失时,整个屏幕随着键盘移动,这两种方法都有弊端,让我们分类讨论下:

1. 输入栏随着键盘移动

  • 当消息条数较少时,键盘不会遮挡住消息
  • 消息条数多了以后,键盘会遮挡住屏幕中处在键盘位置的消息
  • 每次发送了新的消息,用户无法及时看到(因为被键盘遮住了)

结论:体验不好

2. 屏幕随着键盘移动

  • 消息多了以后,能在屏幕上及时看到最新的消息
  • 但消息少的时候,由于键盘把整个 view 顶出屏幕,用户看不到这头几条消息
  • 当消息没有占满整个屏幕的时候,键盘把 view 顶上去,view 底部会留下一段空白

结论:还是体验不好

上述两种情况的图片我就不发了,大家自己脑补一下

那么作为强迫症,怎么能容忍这种不好的体验?于是开始死磕,首先参考了下日常使用最多的微信、qq,分情况总结了一下微信、qq里键盘弹出的效果

  • 情况一:消息较少时(当键盘弹出不会遮挡住消息)聊天界面不动,键盘弹出时只有输入栏上滑,这样保证了最开始的几条消息能完整显示
  • 情况二:消息较多但还未占满屏幕时(当键盘弹出会遮挡住部分消息),键盘弹出时输入栏上滑,同时聊天界面也上滑。注意:此时输入栏上滑的距离为键盘高度,聊天界面上滑距离为键盘可能遮挡住消息的高度
  • 情况三:消息占满或超出屏幕时,键盘弹出时整个 view 上滑
  • 这其中还包括了发送消息时,聊天界面上滑,保证最后一条消息显示在键盘上方的处理。

如果大家不方便脑补,直接掏出手机,用微信或qq和女神聊个天吧

下面,我们放出代码分析:

布局

首先导入 SnapKit 布局框架,对聊天界面和输入栏进行约束

由于我懒,怎么使用 Snapkit 就不赘述 😁

toolBarView.snp.makeConstraints { (make) in
 make.left.equalTo(view.snp.left)
 make.right.equalTo(view.snp.right)
 make.height.equalTo(toolBarHeight)
 make.bottom.equalTo(view.snp.bottom)
}

chatTableView.snp.makeConstraints { (make) in
 make.left.equalTo(view.snp.left)
 make.right.equalTo(view.snp.right)
 make.bottom.equalTo(toolBarView.snp.top)
 make.top.equalTo(view.snp.top).offset(64)
}
</div>

这里让聊天界面的底部和输入栏的上方贴合

监听

监听键盘的弹出和消失

NotificationCenter.default.addObserver(self, 
selector: #selector(keyBoardWillShow(notification:)), name: NSNotification.Name.UIKeyboardWillShow, 
object: nil)

NotificationCenter.default.addObserver(self, 
selector: #selector(keyBoardWillHide(notification:)), name: NSNotification.Name.UIKeyboardWillHide, 
object: nil)
</div>

当键盘弹出时,会触发 keyBoardWillShow(notification:) 方法,键盘消失时,会触发 keyBoardWillHide(notification:) 方法,我们很多复杂的逻辑,都要在这两个方法中实现。另外,Swift 3.1 的版本中,把很多方法的 NS 前缀去除了,所以还在用 Swift 2.3 的童鞋,在NotificationCenter 前面加上 NS 前缀就可以了。

下面重头戏来了,实现上述三种情况的效果

效果

弹出动画

想要 view 随着键盘弹出上滑,需要得到键盘的高度和键盘弹出动画的时间,这里我们通过如下代码得到:

func keyBoardWillShow(notification: Notification) {
 let userInfo = notification.userInfo! as Dictionary
 let value = userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue
 let keyBoardRect = value.cgRectValue
 // 得到键盘高度
 let keyBoardHeight = keyBoardRect.size.height
 mKeyBoardHeight = keyBoardHeight

 // 得到键盘弹出所需时间
 let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
 mKeyBoardAnimateDuration = duration.doubleValue

 ...
}
</div>

然后实现动画

之前在实现输入栏随着键盘弹出的时候,尝试过两种写法:

1、更新 frame

var animate: (()->Void) = {
 let newFrame = CGRect(x: 0, y: 0, width: SCREEN_WIDTH, height: SCREEN_HEIGHT - mKeyBoardHeight)
 self.toolBarView.frame = newFrame
}

UIView.animate(withDuration: mKeyBoardAnimateDuration,
 delay: 0, options: options, animations: animate)
</div>

2、更新约束

var animate: (()->Void) = {
 self.toolBarView.snp.updateConstraints(closure: { (make) in
 make.bottom.equalTo(self.view.snp_bottom).offset(-mKeyBoardHeight) 
 }
}

UIView.animate(withDuration: mKeyBoardAnimateDuration,
 delay: 0, options: options, animations: animate)
</div>

但最后发现,由于滑动的速度不一样,会造成键盘弹出和输入栏上滑时出现缝隙。一句话,体验不好。

于是去网上找了一种方法(必须要感谢下那位大哥),利用一个动画的 options,和 view 的 transform 方法完美解决问题。让 view 和键盘滑动时无缝贴合、如丝般顺滑。

方法如下:

处理所需的动画

var animate: (()->Void) = {
 self.toolBarView.transform = CGAffineTransform(translationX: 0, y: -keyBoardHeight)
}
</div>

创建动画 options

let options = UIViewAnimationOptions(rawValue: 
UInt((userInfo[UIKeyboardAnimationCurveUserInfoKey] 
as! NSNumber).intValue << 16))
</div>

实现动画

UIView.animate(withDuration: mKeyBoardAnimateDuration,
 delay: 0, options: options, animations: animate)
</div>

如此这般,大功告成!亲个嘴儿 😙

现在有了丝滑的滑动效果,我们来处理上述分析的三种情况

定义情况

首先定义效果枚举类型,枚举的好处就不赘述了

enum AnimateType {
 case animate1 // 键盘弹出的话不会遮挡消息
 case animate2 // 键盘弹出的话会遮挡消息,但最后一条消息距离输入框有一段距离
 case animate3 // 最后一条消息距离输入框在小范围内,这里设为 30
}
</div>

枚举类型对应了上述分析的三种效果

让我们回顾一下三种情况

  • 情况一:消息较少时(当键盘弹出不会遮挡住消息)聊天界面不动,键盘弹出时只有输入栏上滑,这样保证了最开始的几条消息能完整显示
  • 情况二:消息较多但还未占满屏幕时(当键盘弹出会遮挡住部分消息),键盘弹出时输入栏上滑,同时聊天界面也上滑。注意:此时输入栏上滑的距离为键盘高度,聊天界面上滑距离为键盘可能遮挡住消息的高度
  • 情况三:消息占满或超出屏幕时,键盘弹出时整个 view 上滑

实现

当消息数量为 0 时,默认动画为输入框滑动

var animate: (()->Void) = {
 self.toolBarView.transform = CGAffineTransform(translationX: 0, y: -keyBoardHeight)
}
</div>

当消息数量不为 0 时,需要进行计算判断情况

首先得到最后一条消息在屏幕的位置,其中 cellDistance 就是最后一条消息相对于当前屏幕的 y 值

let lastIndex = IndexPath(row: msgList.count - 



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Swift 3.1聊天界面键盘效果的实现详解

相关文章

  • 2017-05-28Mybatis接口式编程的原理
  • 2017-05-28史上最简单的MyBatis动态SQL入门示例代码
  • 2017-05-28Swift在控件中添加点击手势的方法
  • 2017-05-28swift 可选型的使用详解
  • 2017-05-28Swift 3.1聊天界面键盘效果的实现详解
  • 2017-05-28Swift中动态调用实例方法介绍
  • 2017-05-28Swift hello world!Swift快速入门教程
  • 2017-05-28Swift中 !和 ?的区别及使用
  • 2017-05-28Swift编程中的一些类型转换方法详解
  • 2017-05-28Swift实现快速排序算法的代码示例

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Swift用final关键字来防止重写
    • Swift心得笔记之控制流
    • 详解Swift编程中的常量和变量
    • 网络爬虫案例解析
    • Swift教程之闭包详解
    • Swift与Objective C的简单对比
    • Swift中实现点击、双击、捏、旋转、拖动、划动、长按手势的类和方法介绍
    • Swift中用到extension的一些基本的扩展功能讲解
    • 详解在swift中实现NSCoding的自动归档和解档
    • Servlet3.0实现文件上传的方法

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有