swift实现ios类似微信输入框跟随键盘弹出的效果
为什么要做这个效果
在聊天app,例如微信中,你会注意到一个效果,就是在你点击输入框时输入框会跟随键盘一起向上弹出,当你点击其他地方时,输入框又会跟随键盘一起向下收回,二者完全无缝连接,那么这是怎么实现的呢,也许你会说直接在键盘弹出的时候把输入框也向上移动不就行了?但是我使用这种方法的时候,发现效果十分不理想,会有明显的滞后现象,原因有以下几点:
1.键盘弹出动画并不是匀速,键盘和输入框的时间曲线不完全一致,运动不同步
2.各种键盘的高度不一样(比如搜狗输入法就比系统自带键盘要高)
3.无法确定键盘动画的时间,会导致延迟
解决方案
使用本地通知,对键盘的状态(弹出、收回)进行监控,当键盘状态发生改变时,在相应的方法中对输入框的位置进行操作。
这里应用了两种在ios编程中很重要的思想:
Key-value coding(KVC) 和key-value observing(KVO)
1.使用NSNotificationCenter.defaultCenter().addObserver()添加对UIKeyboardWillShowNotification和UIKeyboardWillHideNotification键的监控,当这些值发生改变时发送通知
NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyBoardWillShow:", name:UIKeyboardWillShowNotification, object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector:"keyBoardWillHide:", name:UIKeyboardWillHideNotification, object: nil)
2.实现两个监控方法
实现键盘弹出的方法:
func keyBoardWillShow(note:NSNotification)
{
//1
let userInfo = note.userInfo as! NSDictionary
//2
var keyBoardBounds = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue()
let duration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
//3
var keyBoardBoundsRect = self.view.convertRect(keyBoardBounds, toView:nil)
//4
var keyBaoardViewFrame = keyBaordView.frame
var deltaY = keyBoardBounds.size.height
//5
let animations:(() -> Void) = {
self.keyBaordView.transform = CGAffineTransformMakeTranslation(0,-deltaY)
if duration > 0 {
let options = UIViewAnimationOptions(UInt((userInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).integerValue << 16))
UIView.animateWithDuration(duration, delay: 0, options:options, animations: animations, completion: nil)
}else{
animations()
}
}
代码分析
//1
let userInfo = note.userInfo as! NSDictionary
将通知的用户信息取出,转化为字典类型,里面所存的就是我们所需的信息:键盘动画的时长、时间曲线;键盘的位置、高度信息。有了这些信息我们就可以do some magic了~
//2
通过对应的键UIKeyboardFrameEndUserInfoKey,取出键盘位置信息
通过UIKeyboardAnimationDurationUserInfoKey,取出动画时长信息
//3
var keyBoardBoundsRect = self.view.convertRect(keyBoardBounds, toView:nil)
由于取出的位置信息是绝对的,所以要将其转换为对应于当前view的位置,否则位置信息会出错!
//4
var keyBaoardViewFrame = keyBaordView.frame
var deltaY = keyBoardBounds.size.height
保存下输入框的位置信息和y坐标需要变换的量以便后面调用
//5
let animations:(() -> Void) = {
self.keyBaordView.transform = CGAffineTransformMakeTranslation(0,-deltaY)
if duration > 0 {
let options = UIViewAnimationOptions(UInt((userInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).integerValue << 16))
UIView.animateWithDuration(duration, delay: 0, options:options, animations: animations, completion: nil)
}else{
animations()
}
}
首先使用仿射变换CGAffineTransformMakeTranslation,使输入框的高度减少deltaY也就是跟随键盘的位置向上移动;
此处难点在这里
let options = UIViewAnimationOptions(UInt((userInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).integerValue << 16))
这里是将时间曲线信息(一个64为的无符号整型)转换为UIViewAnimationOptions类型,要通过左移16来完成类型转换。
这个方法是在一个比较著名的解决bug的网站stackoverflow里找到的。
自我感觉这是比较坑的地方,它居然没有用来进行类型转换的方法,竟然还得要位!运!算!不过相信今后这个坑会被apple填上吧。。
然后呢就是把这些东西全部装进UIView的动画函数中,执行动画。
UIView.animateWithDuration(duration, delay: 0, options:options, animations: animations, completion: nil)
这样键盘弹出的方法就完全实现了!
接下来就是收回键盘的部分了:
这部分呢就比较简单了,收回键盘时只需要动画时长duration和时间曲线信息options所以只要留下他们就行了,然后再将输入框的位置还原即可,这里有一个很巧妙的办法
self.keyBaordView.transform = CGAffineTransformIdentity
这样就可以还原所有变换~
下面是该方法的实现:
func keyBoardWillHide(note:NSNotification)
{
let userInfo = note.userInfo as! NSDictionary
let duration = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber).doubleValue
let animations:(() -> Void) = {
self.keyBaordView.transform = CGAffineTransformIdentity
}
if duration > 0 {
let options = UIViewAnimationOptions(UInt((userInfo[UIKeyboardAnimationCurveUserInfoKey] as! NSNumber).integerValue << 16))
UIView.animateWithDuration(duration, delay: 0, options:options, animations: animations, completion: nil)
}else{
animations()
}
}
实际上这个方法不会运行,因为并没有判断是否应该收回键盘,我的解决方法是当手指点击输入框之上的任何地方就会收回键盘,这个在我的完整demo会看到。
demo的效果:
原文链接:http://www.jianshu.com/p/4e755fe09df7
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。
swift实现ios类似微信输入框跟随键盘弹出的效果的更多相关文章
- 【转】swift实现ios类似微信输入框跟随键盘弹出的效果
swift实现ios类似微信输入框跟随键盘弹出的效果 为什么要做这个效果 在聊天app,例如微信中,你会注意到一个效果,就是在你点击输入框时输入框会跟随键盘一起向上弹出,当你点击其他地方时,输入框又会 ...
- 【土旦】vue 解决ios H5底部输入框 获取焦点时弹出虚拟键盘挡住输入框 以及监听键盘收起事件
问题描述 im聊天H5页面,在iOS系统下,inpu获取焦点弹出系统虚拟键盘时,会出现挡住input的情况,十分影响用户体验. bug图 解决方法: html: <input type=&quo ...
- 微信浏览器软键盘弹出与页面resize的问题
使用微信打开网页,弹出软键盘时遇到的兼容问题 过去开发中遇到过很多这种情况,页面底部需要固定定位一个按钮,广告栏或者菜单栏,页面中有表单项需要填写,在打开手机虚拟键盘的时候,底部固定定位的元素会处在软 ...
- Android封装类似微信的顶部TitleBar弹出的PopupWindow代码
Android仿微信顶部titlebar,点击加号弹出的PopupWindow,是封装好的PopupWindow,直接拿来用即可,先看效果图: 调用代码非常简单,这是MainActivity的代码: ...
- ToolBar跟随键盘弹出和隐藏
实现效果如下: 代码实现如下: // // ViewController.m // PopToolBarDemo // // Created by 思 彭 on 2017/7/20. // Copyr ...
- iOS 键盘弹出遮挡输入框
#pragma mark 键盘弹出遮挡输入框 //开始编辑输入框的时候,软键盘出现,执行此事件 -(void)textFieldDidBeginEditing:(UITextField *)textF ...
- iOS学习——键盘弹出遮挡输入框问题解决方案
在iOS或Android等移动端开发过程中,经常遇到很多需要我们输入信息的情况,例如登录时要输入账号密码.查询时要输入查询信息.注册或申请时需要填写一些信息等都是通过我们键盘来进行输入的,在iOS开发 ...
- iOS学习——tableview中带编辑功能的cell键盘弹出遮挡和收起问题解决
最近在项目中经常用到UITableView中的cell中带有UITextField或UITextView的情况,然后在这种场景下,当我们点击屏幕较下方的cell进行编辑时,这时候键盘弹出来会出现遮挡待 ...
- Android软键盘弹出,覆盖h5页面输入框问题
之前我们在使用vue进行 h5 表单录入的过程中,遇到了Android软键盘弹出,覆盖 h5页面 输入框 问题,在此进行回顾并分享给大家: 系统:Android 条件:当输入框在可视区底部或者偏下的位 ...
随机推荐
- Cacti以MB为单位监控流量
Cacti自带的流量监控阀值模板为“Interface – Traffic”,只能监控bytes,在添加阀值之后,报警的流量信息以bytes为单位,查看很不友好,可以通过以下方法将btyes转换成MB ...
- oracle死锁模拟
环境介绍: 用户test01 创建表tab01,用户test02创建表tab02.Test01 更新tab01不提交,test02 更新表tab02不提交.然后test01 更新test02下的表ta ...
- ASP.NET菜鸟之路之Seesion小例子
背景 我是一个ASP.NET菜鸟,暂时开始学习ASP.NET,在此记录下我个人敲的代码,没有多少参考价值,请看到的盆友们为我点个赞支持我一下,多谢了. Session介绍 Session保存特定用户相 ...
- 使用GitBook编写文档
GitBook 简介 GitBook 是一个通过 Git 和 Markdown 来撰写书籍的工具,最终可以生成 3 种格式: 静态站点:包含了交互功能(例如搜索.书签)的站点 PDF:PDF 格式的文 ...
- jQuery 做好七件事帮你提升jQuery的性能
1. Append Outside of Loops 凡是触及到DOM都是有代价的.如果你向DOM当中附加大量的元素,你会想一次性将它们全部附加进来,而不是分多次进行.当在循环当中附加元素就会产生一个 ...
- [HTML5 Canvas学习]绘制矩形
1.使用strokeRect和fillRect方法绘制矩形 a.strokeRect是绘制一个不填充的矩形 b.fillRect是绘制一个填充的矩形 代码: <script> var ca ...
- PHP开发套件
Windows系统下开发 环境配置: PHPstudy----立即下载 开发工具: PHPstorm----立即下载 引用一个注册服务器地址:潘田--phpstorm 2016.1注册码 当然推荐大家 ...
- Asp.net mvc中Controller的返回值
(1)EmptyResult:当用户有误操作或者是图片防盗链的时候,这个EmptyResult就可以派上用场,返回它可以让用户啥也看不到内容,通过访问浏览器端的源代码,发现是一个空内容: public ...
- elasticsearch 安装
### USAGE ### ### ./ElasticSearch.sh 1.5.0 will install Elasticsearch 1.5.0 ### ./ElasticSearch.sh 1 ...
- python中read、readline和readlines的区别
read 读取整个文件 readline 读取下一行 readlines 读取整个文件到一个迭代器以供我们遍历(读取到一个list中,以供使用,比较方便). 123.txt内容 ...