封面(图文无关)

为什么要做这个效果


在聊天app,例如微信中,你会注意到一个效果,就是在你点击输入框时输入框会跟随键盘一起向上弹出,当你点击其他地方时,输入框又会跟随键盘一起向下收回,二者完全无缝连接,那么这是怎么实现的呢,也许你会说直接在键盘弹出的时候把输入框也向上移动不就行了?但是我使用这种方法的时候,发现效果十分不理想,会有明显的滞后现象,原因有以下几点:
1.键盘弹出动画并不是匀速,键盘和输入框的时间曲线不完全一致,运动不同步
2.各种键盘的高度不一样(比如搜狗输入法就比系统自带键盘要高)
3.无法确定键盘动画的时间,会导致延迟

解决方案


使用本地通知,对键盘的状态(弹出、收回)进行监控,当键盘状态发生改变时,在相应的方法中对输入框的位置进行操作。

这里应用了两种在ios编程中很重要的思想:Key-value coding (KVC) 和 key-value observing (KVO)

1.使用NSNotificationCenter.defaultCenter().addObserver()添加对UIKeyboardWillShowNotificationUIKeyboardWillHideNotification键的监控,当这些值发生改变时发送通知

    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源代码github

demo的效果:

键盘弹出demo.gif
文/codeGlider(简书作者)
原文链接:http://www.jianshu.com/p/4e755fe09df7
著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。

swift实现ios类似微信输入框跟随键盘弹出的效果的更多相关文章

  1. 【转】swift实现ios类似微信输入框跟随键盘弹出的效果

    swift实现ios类似微信输入框跟随键盘弹出的效果 为什么要做这个效果 在聊天app,例如微信中,你会注意到一个效果,就是在你点击输入框时输入框会跟随键盘一起向上弹出,当你点击其他地方时,输入框又会 ...

  2. 【土旦】vue 解决ios H5底部输入框 获取焦点时弹出虚拟键盘挡住输入框 以及监听键盘收起事件

    问题描述 im聊天H5页面,在iOS系统下,inpu获取焦点弹出系统虚拟键盘时,会出现挡住input的情况,十分影响用户体验. bug图 解决方法: html: <input type=&quo ...

  3. 微信浏览器软键盘弹出与页面resize的问题

    使用微信打开网页,弹出软键盘时遇到的兼容问题 过去开发中遇到过很多这种情况,页面底部需要固定定位一个按钮,广告栏或者菜单栏,页面中有表单项需要填写,在打开手机虚拟键盘的时候,底部固定定位的元素会处在软 ...

  4. Android封装类似微信的顶部TitleBar弹出的PopupWindow代码

    Android仿微信顶部titlebar,点击加号弹出的PopupWindow,是封装好的PopupWindow,直接拿来用即可,先看效果图:  调用代码非常简单,这是MainActivity的代码: ...

  5. ToolBar跟随键盘弹出和隐藏

    实现效果如下: 代码实现如下: // // ViewController.m // PopToolBarDemo // // Created by 思 彭 on 2017/7/20. // Copyr ...

  6. iOS 键盘弹出遮挡输入框

    #pragma mark 键盘弹出遮挡输入框 //开始编辑输入框的时候,软键盘出现,执行此事件 -(void)textFieldDidBeginEditing:(UITextField *)textF ...

  7. iOS学习——键盘弹出遮挡输入框问题解决方案

    在iOS或Android等移动端开发过程中,经常遇到很多需要我们输入信息的情况,例如登录时要输入账号密码.查询时要输入查询信息.注册或申请时需要填写一些信息等都是通过我们键盘来进行输入的,在iOS开发 ...

  8. iOS学习——tableview中带编辑功能的cell键盘弹出遮挡和收起问题解决

    最近在项目中经常用到UITableView中的cell中带有UITextField或UITextView的情况,然后在这种场景下,当我们点击屏幕较下方的cell进行编辑时,这时候键盘弹出来会出现遮挡待 ...

  9. Android软键盘弹出,覆盖h5页面输入框问题

    之前我们在使用vue进行 h5 表单录入的过程中,遇到了Android软键盘弹出,覆盖 h5页面 输入框 问题,在此进行回顾并分享给大家: 系统:Android 条件:当输入框在可视区底部或者偏下的位 ...

随机推荐

  1. adb shell - device not found

    如果是真机,则连接usb即可(我的是真机).

  2. iOS开发之Quartz2D详解

    1. 什么是Quartz2D? Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片( ...

  3. uva 11529 Strange Tax Calculation (几何+计数)

    题目链接: http://vjudge.net/problem/viewProblem.action?id=18277 这题暴力n^4妥妥的TLE!即使n^3也可能会T 正确的姿势应该是:枚举每个点作 ...

  4. 【USACO 1.3.2】修理牛棚

    [描述] 在一个夜黑风高,下着暴风雨的夜晚,farmer John的牛棚的屋顶.门被吹飞了. 好在许多牛正在度假,所以牛棚没有住满. 牛棚一个紧挨着另一个被排成一行,牛就住在里面过夜. 有些牛棚里有牛 ...

  5. Skew Join与Left Semi Join相关

    Skew Join 真实数据中数据倾斜是一定的, hadoop 中默认是使用 hive.exec.reducers.bytes.per.reducer = 1000000000 也就是每个节点的red ...

  6. C# 根据IP查询地址归属地

    必备文件:IPLocation.dll.QQWry.Dat 下载地址:http://pan.baidu.com/s/1jG1dlOy (可百度下载) 之前有过将 QQWry.Dat 转为 Access ...

  7. Linux imagemagic(转载)

    原文地址:http://linux.chinaitlab.com/c/803455.html 更多详细使用示例请参考:http://www.ibm.com/developerworks/cn/open ...

  8. thinkphp ajax 实例 实现

    thinkPHP后台实现 #删除用户操作      function delete()      {        if(isset($_SERVER["HTTP_X_REQUESTED_W ...

  9. django HttpRequest

    request.path 除域名以外的请求路径,以正斜杠开头 "/hello/" request.get_host() 主机名(比如,通常所说的域名) "127.0.0. ...

  10. How to create Managed Metadata Column

    This article introduce how to create/use managed metadata column from List. First, we need to config ...