V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
tunnyios
V2EX  ›  iOS

封装一个键盘控制器(带有工具条)作为基类

  •  
  •   tunnyios · 2015-07-21 00:20:47 +08:00 · 2002 次点击
    这是一个创建于 3417 天前的主题,其中的信息可能已经有所发展或是发生改变。
    http://tunnyios.github.io/personal/keyboard/
    ##键盘工具条的使用

    开发中经常会跟键盘打交道,键盘上添加工具条,可以方便的应对一些多textField的界面操作。如果一个项目中多处用到类似的含有工具条的键盘处理,可以使用封装的思想,实现一个基类。需要用到的地方直接继承这个基类即可。

    下面说说实现的方法,以及遇到的问题:
    <!--more-->

    ###xib自定义inputAccessoryView

    这里不需要多说什么,主要是实现"上一个" "下一个" "完成"这三个功能,通过代理的方式交给baseKeyboardViewController来实现。

    ###baseKeyboardViewController的实现

    1. 使用数组存储textField容器视图中所有的textField
    2. 实现代理方法,获取当前响应的textfield的在textFieldArray中的索引来更改第一响应者
    3. 使用通知来监听键盘Frame的改变,调整self.view视图的位置

    ###核心代码

    {% highlight objective-c %}

    /** 键盘事件处理 */
    - (void)keyboradChangedFrame:(NSNotification *)nofi
    {

    //当键盘即将改变frame的时候,调整view的frame
    //1. 获取当前的键盘的第一响应者index
    NSInteger textIndex = [self getCurrentTextIndex];
    //2. 取当前第一响应者的最大Y值
    //转换坐标系到self.view
    CGRect textFrame = [self.textFieldArray[textIndex] convertRect:[self.textFieldArray[textIndex] bounds] toView:self.view];
    CGFloat textY = CGRectGetMaxY(textFrame);
    //3. 获取当前键盘所占的view的高度
    CGRect keyboradFrame = [nofi.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat keyboradSizeY = self.view.bounds.size.height - keyboradFrame.origin.y;
    //4. 两个高度相加与控制器的高度进行比较
    CGFloat changeFrame = self.view.bounds.size.height - (textY + keyboradSizeY);
    if (changeFrame < 0) {
    //调整view位置
    [UIView animateWithDuration:0.3 animations:^{
    self.view.transform = CGAffineTransformMakeTranslation(0, changeFrame);
    }];
    }
    DLog(@"%@", nofi);
    }

    /** 键盘的代理方法 */
    - (void)keyboardTool:(HCKeyboardTool *)keyboardTool didClickItemType:(KeyboardItemType)itemType
    {

    //1. 获取当前响应的textfield的在textFieldArray中的索引
    NSInteger textIndex = [self getCurrentTextIndex];

    if (KeyboardItemTypePrevious == itemType) {
    //上一步
    [self previousClickWithIndex:textIndex];
    } else if (KeyboardItemTypeNext == itemType) {
    //下一步
    [self nextClickWithIndex:textIndex];
    } else {
    //完成
    [self doneClickWithIndex:textIndex];
    }
    }

    /** 下一步 */
    - (void)nextClickWithIndex:(NSInteger)textIndex
    {
    if (textIndex < (self.textFieldArray.count - 1)) {
    //更改第一响应者
    /* 先取消第一响应者,可以让键盘的位置改变一次,这样就可以触发一次键盘 frame改变事件 */
    [self.textFieldArray[textIndex] resignFirstResponder];
    [self.textFieldArray[textIndex + 1] becomeFirstResponder];
    }
    }

    /** 完成 */
    - (void)doneClickWithIndex:(NSInteger)textIndex
    {
    //退出键盘
    [self.view endEditing:YES];
    //view的frame回到初值****
    [UIView animateWithDuration:0.3 animations:^{
    self.view.transform = CGAffineTransformIdentity;
    }];
    }

    {% endhighlight %}

    ###注意的问题

    1. 如果在程序中多个控制器分别继承了该基类,一定要注意:移除通知的时机,如果控制器没有被销毁,则需要手动在子类控制器中手动移除通知。否则通知中的处理会混乱。
    2. 要注意textfield的顺序,是跟添加到其父视图中顺序是一致的。

    ###效果图演示

    ![](http://7xke07.com1.z0.glb.clouddn.com/image/keyboard_ok.gif)

    ###demo代码分享

    链接: http://pan.baidu.com/s/1jGznMbO 密码: 347m
    1 条回复    2015-07-21 08:36:06 +08:00
    dcty
        1
    dcty  
       2015-07-21 08:36:06 +08:00   ❤️ 1
    https://github.com/hackiftekhar/IQKeyboardManager
    https://github.com/michaeltyson/TPKeyboardAvoiding
    这两个用起来都很无痛,没有什么需要注意的地方。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5210 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 09:41 · PVG 17:41 · LAX 01:41 · JFK 04:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.