iOS 输入框和键盘的斗争(一)

在开发的过程中,难免遇到在一个页面中用户需要输入许多的数据,也有可能跳转的下一个页面也涉及到多个输入框。


如果产品经理一意孤行的话,那么只能和键盘进行斗争了。因为刚接手项目时第一次发现由于监听导致页面上移等乱七八糟的问题,所以以下图的两个页面中的textField为例:

UITextField键盘监听例图
版本一

刚接手项目的第一个版本,即将上线前一天出现了页面滑动的错误。



类似于上面的例图,两个跳转页面中都需要进行键盘的监听。而出现问题的主要原因是:两个页面中的键盘监听互相影响了。
对键盘的出现和消失监听的位置一般在viewDidLoad方法中

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showKeyboardHandler:) name:UIKeyboardWillShowNotification object:nil];
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hiddenKeyboardhandler:) name:UIKeyboardWillHideNotification object:nil];

移除对键盘的监听在viewWillDisappear方法中:

[[NSNotificationCenter defaultCenter] removeObserver:self];

对正常单一页面输入框的处理没有问题,但是在多个页面都存在键盘监听的情况下会出现监听到不合时宜的键盘通知,通过页面跳转方法调用的顺序即可知:

secondVC ——>viewDidLoad                      1
firstVC ——>viewWillDisappear                 2
secondVC  ———>viewWillAppear                 3
firstVC ———>viewDidDisappear                 4
secondVC ——>viewDidAppear                    5

也就是说当页面1还在监听键盘时,页面2也开始监听。如果用户在页面1输入的过程中直接进入页面2,系统回调UIKeyboardWillHideNotification通知给页面1时,这时候页面2也会接收到隐藏键盘的通知。
所以在页面2添加监听前必须除去页面1中的键盘监听方法。

版本二

第一个版本成功上线后,该页面出现了两个新的需求:

① 自定义键盘

之前想着是有什么难的:就是在监听键盘出现的方法中,定义一个CustomKeyboardView放在keyWindow上,覆盖系统的keyboard。实际做了才发现:


将CustomKeyboardView添加到keyWindow上

CustomKeyboardView在keyboardWillShow的通知方法中添加到keyWindow上,只会被系统键盘覆盖。
所以必须将CustomKeyboardView添加到最上方的window上:

window = [[[UIApplication sharedApplication] windows]lastObject];
将CustomKeyboardView覆盖系统的键盘

这种方法系统的键盘还是会弹出,动画效果不是很好,而且textField提供了设置自定义键盘更直接的方式---通过设置inputView:

CustomKeyboard *customKeyboard = [[CustomKeyboard alloc] initWithFrame:CGRectZero];
self.textField.inputView = customKeyboard;

事实证明未实际做的有可能全错。

② 备注的输入框随着行数变化其高度

中午暖暖的阳光中,一看需求的时候,直接想着封装一个基于TextField的view,监听其高度的变化。等下午开始写的时候:


使用TextField计算高度
@interface UITextField : UIControl

UITextField直接继承与UIControl,一行直接写到底,压根就不会换行。能换行的输入框是UITextView:

@interface UITextView : UIScrollView 

继承于UIScrollView,定义maxRow,当行数超过该定义值直接将scrollEnabled开启。

计算一行的高度

一般会直接使用系统提供的方法计算label整个内容的高度:

 [self.textView.text boundingRectWithSize:CGSizeMake(width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15]} context:nil]

但是对于textView而言,因为会自动换行,所以只需要计算一行的高度即可:字体的高度 + 距离top的高度约束 + 距离bottom的高度约束:

CGFloat height = ceilf([self.textView sizeThatFits:CGSizeMake(self.textView.frame.size.width, MAXFLOAT)].height);

其实在项目中除了新开发的需求之外,还有一个硬性的优化需求:

在键盘显示的时候如何简单的向上移动被遮盖的输入框?

之前想着通过计算每一个cell中textField在tableView中的(x,y)值来上移一定的距离,但是操作起来还是麻烦不已。因为在项目中整个页面中基本上全是输入框,所以参考了第三方库 IQKeyboardManager,用于处理键盘遮罩的问题。

pod 'IQKeyboardManager'
IQKeyboardManager

该篇中将使用方式和参数的设置进行讲解,具体的等到下一篇中详解。

① 全局参数设置
//设置全局参数
    IQKeyboardManager *keyboardManager = [IQKeyboardManager sharedManager];
    //开启功能 --->如果全局设置了YES,那么每一个类默认都是开启该功能的。
    keyboardManager.enable = NO;
    //点击背景是否将键盘收起
    keyboardManager.shouldResignOnTouchOutside = YES;
    //控制键盘上toolBar的字体颜色是否由用户自己控制
    keyboardManager.shouldToolbarUsesTextFieldTintColor = YES;
    //当有多个输入框的时,如何识别不同的输入框进行跳转
    keyboardManager.toolbarManageBehaviour = IQAutoToolbarBySubviews;
    //是否显示键盘上的toolBar
    // Automatic add IQToolbar functionality. Default is YES.   自动添加IQToolbar的功能。默认为YES  
    keyboardManager.enableAutoToolbar = YES; 
    //是否将textField的placeholder显示
    /**
     If YES, then it add the textField's placeholder text on IQToolbar. Default is YES.
     */
    keyboardManager.shouldShowToolbarPlaceholder = YES;
    keyboardManager.placeholderFont = [UIFont systemFontOfSize:15];
    //输入框距离键盘顶部的距离
    keyboardManager.keyboardDistanceFromTextField = 10.0f;

重点说明一下:

textField发出开始编辑的通知后,IQKeyboardManager会监听键盘的出现消失以及textField、textView的开始编辑和结束编辑的通知,所以当enable=YES后,已经为项目中配置好该功能

所以在弄完上面的配置后,不要怀疑直接在需要的类中开启该功能即可使用,因为全是通知进行沟通。

②textField和textView的发出通知的顺序

在该类中对textField和textView分别进行开始编辑通知的监听以及键盘出现和消失的监听.

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textFieldBeginEditing:) name:UITextFieldTextDidBeginEditingNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewBeginEditing:) name:UITextViewTextDidBeginEditingNotification object:nil];

结果很有意思:

textField:
  textFieldBeginEditing:
  keyboardWillShowHandler:
  keyboardDidShowHandler:
textView:
  keyboardWillShowHandler:
  textViewBeginEditing:
  keyboardDidShowHandler:

为两者的不同再加一笔。


在实际的开发中,输入框有挺多值得注意的地方,如使用以下的方法获得变化的text值:

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string

该方法会导致无法获得最后一个字符,可以使用:

 [self.textField addTarget:self action:@selector(changeTextHandler) forControlEvents:UIControlEventEditingChanged]
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,099评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,828评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,540评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,848评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,971评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,132评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,193评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,934评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,376评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,687评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,846评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,537评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,175评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,887评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,134评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,674评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,741评论 2 351

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,067评论 4 62
  • 本来的信心满满,却因为自以为是的态度浪费了太多的时间。如今从头开始的感觉真是爽极了。
    千浮生阅读 177评论 0 0
  • 又是一桩悲剧,成了新闻。这是最好的时代,也是从不乏天灾人祸的时代。 事件:7月23日下午3时许,北京延庆,八达岭野...
    方童依桐_艺童访桐阅读 738评论 8 10