• ios中键盘处理源码


     

    1:先分别设置各个文本框的键盘类型(inputview)-->在特定键盘中textediting中禁用输入。

    
    


    2:然后递归绑定各个键盘的工具条(inputaccessview).
    并且个各个控件绑定有顺序的tag

    
    

    3:上一个和下一个功能:先找到第一响应者,然后利用tag进行切换第一响应者。
    注意点(
    1:当前tag等于最小tag,工具条的上一个禁掉--》在循环中
    2:当前编辑的时候,判断tag和最小tag进行判断,是否禁用上一个--》在文本框代理中



    //
    MJScrollView.m // 动画和事件综合例子-键盘处理 // // Created by mj on 13-4-15. // Copyright (c) 2013年 itcast. All rights reserved. // #import "MJScrollView.h" #import "UIView+Add.h" @interface MJScrollView () { CGPoint _lastOffset; } @end @implementation MJScrollView #pragma mark - 生命周期方法 - (id)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self initial]; } return self; } - (id)init { if (self = [super init]) { [self initial]; } return self; } #pragma mark 当MJScrollView从xib中创建完毕后会调用这个方法 - (void)awakeFromNib { [self initial]; } - (void)dealloc { NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; // 注意:记得要移除 [center removeObserver:self]; [super dealloc]; } #pragma mark 初始化 - (void)initial { self.contentSize = self.bounds.size; NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; // 注册键盘显示的通知 [center addObserver:self selector:@selector(keybordWillShow:) name:UIKeyboardWillShowNotification object:nil]; // 注册键盘隐藏的通知 [center addObserver:self selector:@selector(keybordWillHide:) name:UIKeyboardWillHideNotification object:nil]; } #pragma mark 键盘显示出来的时候调用 - (void)keybordWillShow:(NSNotification *)notification{ //NSLog(@"keybordWillShow,%@", notification); CGRect keyboardRect = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; UITextField *textField = [UIView findFistResponder:self]; // toView用nil值,代表UIWindow CGRect convertRect = [textField convertRect:textField.bounds toView:nil]; CGFloat distance = keyboardRect.origin.y - (convertRect.origin.y + convertRect.size.height + 10); if (distance < 0) { // 说明键盘挡住了文本框 [self animationWithUserInfo:notification.userInfo block:^{ CGPoint offset = _lastOffset = self.contentOffset; offset.y -= distance; self.contentOffset = offset; }]; } } #pragma mark 键盘隐藏的时候调用 - (void)keybordWillHide:(NSNotification *)notification { [self animationWithUserInfo:notification.userInfo block:^{ self.contentOffset = _lastOffset; }]; } #pragma mark 抽出一个方法来执行动画 - (void)animationWithUserInfo:(NSDictionary *)userInfo block:(void (^)(void))block { // 取出键盘弹出的时间 CGFloat duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]; // 取出键盘弹出的速率节奏 int curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]; [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:duration]; [UIView setAnimationCurve:curve]; // 调用block block(); [UIView commitAnimations]; } #pragma mark 监听scrollview点击 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { // 退出键盘 [self endEditing:YES]; } @end
    @implementation UIView (Add)
    #pragma mark 递归找出第一响应者
    + (UITextField *)findFistResponder:(UIView *)view {
        for (UIView *child in view.subviews) {
            if ([child respondsToSelector:@selector(isFirstResponder)]
                &&
                [child isFirstResponder]) {
                return (UITextField *)child;
            }
            
            UITextField *field = [self findFistResponder:child];
            if (field) {
                return field;
            }
        }
        
        return nil;
    }
    @end
    
    //
    //  MJViewController.m
    //  动画和事件综合例子-键盘处理
    //
    //  Created by mj on 13-4-15.
    //  Copyright (c) 2013年 itcast. All rights reserved.
    //
    
    #import "MJViewController.h"
    #import "KeyboardTool.h"
    #import "UIView+Add.h"
    
    // 文本框最小的tag
    #define kTextFieldMinTag 10
    
    @interface MJViewController () {
        KeyboardTool *_tool;
        // 文本框的总数
        int _textFieldCount;
    }
    @end
    
    @implementation MJViewController
    
    #pragma mark - 生命周期方法
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        // 初始化生日文本框
        [self initBirthday];
        
        // 初始化性别文本框
        [self initSex];
        
        // 给所有的文本框绑定KeyboardTool
        KeyboardTool *tool = [KeyboardTool keyboardTool];
        tool.delegate = self;
        [self initKeyboardTool:tool view:self.view];
        _tool = tool;
    }
    
    #pragma mark - KeyboardTool代理方法
    - (void)keyboardTool:(KeyboardTool *)tool buttonClick:(KeyboardToolButtonType)type {
        // case里面有多行时,写个{}
        
        // 完成
        if (type == kKeyboardToolButtonTypeDone) {
            [self.view endEditing:YES];
        } else { // 下一个 或者 上一个
            
            // 获取当前的第一响应者
            UITextField *responder = [UIView findFistResponder:self.view];
            
            // 取出新的响应者
            int tag = responder.tag;
            
            type == kKeyboardToolButtonTypeNext ? tag++ : tag --;
        
            
            UITextField *newResponder = (UITextField *)[self.view viewWithTag:tag];
            
            // 让newResponder称为第一响应者
            [newResponder becomeFirstResponder];
            
            // 判断是不是最上面的文本框了
            tool.previousBtn.enabled = tag != kTextFieldMinTag;
            
            // 判断是不是最下面的文本框了
            int maxTag = kTextFieldMinTag + _textFieldCount -1;
            tool.nextBtn.enabled = tag != maxTag;
            
    //        if (tag == kTextFieldMinTag) {
    //            tool.previousBtn.enabled = NO;
    //        } else {
    //            tool.previousBtn.enabled = YES;
    //        }
        }
    }
    
    #pragma mar - 给所有的文本框绑定KeyboardTool
    - (void)initKeyboardTool:(KeyboardTool *)tool view:(UIView *)view {
        
        // static不能省略
        //static int i = 0;
        
        for (UITextField *child in view.subviews) {
            if ([child isKindOfClass:[UITextField class]]) {
                child.inputAccessoryView = tool;
                // 绑定tag
                child.tag = kTextFieldMinTag + _textFieldCount;
                
                // 设置文本框的代理
                child.delegate = self;
                
                // 设置文本框的返回键类型
                child.returnKeyType = UIReturnKeyDone;
                
                _textFieldCount ++;
                
                NSLog(@"%@-tag=%i", NSStringFromClass([view class]), child.tag);
            } else { // 搜索里面的文本框
                [self initKeyboardTool:tool view:child];
            }
        }
    }
    
    #pragma mark - 生日
    #pragma mark 初始化生日文本框
    - (void)initBirthday {
        // 初始化一个日期选择控件(不用指定宽高)
        UIDatePicker *picker = [[[UIDatePicker alloc] init] autorelease];
        
        // 设置显示中文
        picker.locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"] autorelease];
        // 只显示年月日
        picker.datePickerMode = UIDatePickerModeDate;
        // 添加值改变的监听器
        [picker addTarget:self action:@selector(birthdayChange:) forControlEvents:UIControlEventValueChanged];
        self.birthday.inputView = picker;
        
        //self.birthday.delegate = self;
    }
    
    #pragma mark 监听日期选择控件的改变
    - (void)birthdayChange:(UIDatePicker *)picker {
        NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
        formatter.dateFormat = @"yyyy-MM-dd";
        self.birthday.text = [formatter stringFromDate:picker.date];
    }
    #pragma mark - UITextField代理方法
    #pragma mark 返回NO代表不允许手动改变文本框的文本
    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
        // 只有生日和性别才不允许修改文字
        return !(textField == self.birthday || textField == self.sex);
    }
    #pragma mark 文本框开始编辑(开始聚焦)
    - (void)textFieldDidBeginEditing:(UITextField *)textField {
        // 判断是不是最上面的文本框了
        _tool.previousBtn.enabled = textField.tag != kTextFieldMinTag;
        
        // 判断是不是最下面的文本框了
        int maxTag = kTextFieldMinTag + _textFieldCount -1;
        _tool.nextBtn.enabled = textField.tag != maxTag;
    }
    #pragma mark 点击了Return按钮
    - (BOOL)textFieldShouldReturn:(UITextField *)textField {
        [self.view endEditing:YES];
        return YES;
    }
    
    #pragma mark - 性别
    #pragma mark 初始化性别文本框
    - (void)initSex {
        UIPickerView *picker = [[[UIPickerView alloc] init] autorelease];
        // 设置数据源
        picker.dataSource = self;
        // 设置代理
        picker.delegate = self;
        // 明显地显示选中了哪一行
        picker.showsSelectionIndicator = YES;
        
        self.sex.inputView = picker;
        
        //self.sex.delegate = self;
    }
    #pragma mark - UIPickerView数据源方法
    #pragma mark 一共有多少列
    - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
        return 1;
    }
    #pragma mark 第component列有多少行
    - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
        return 2;
    }
    
    #pragma mark - UIPickerView代理方法
    // picker的每一行要保证结构是一样
    // reusingView:(UIView *)view就是缓存池中的可循环利用的View
    - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view {
        
        static int iconTag = 10;
        static int labelTag = 20;
        
        // 如果没有可循环利用的View
        if (view == nil) {
            view = [[[UIView alloc] init] autorelease];
            CGFloat viewHeight = 50;
            view.bounds = CGRectMake(0, 0, 100, viewHeight);
            
            // 添加ImageView
            UIImageView *icon = [[[UIImageView alloc] init] autorelease];
            CGFloat iconX = 5;
            CGFloat iconWidth = 32;
            CGFloat iconHeight = 32;
            CGFloat iconY = (viewHeight - iconHeight) * 0.5f;
            icon.frame = CGRectMake(iconX, iconY, iconWidth, iconHeight);
            icon.tag = iconTag;
            [view addSubview:icon];
            
            // 添加文本
            UILabel *label = [[[UILabel alloc] init] autorelease];
            label.frame = CGRectMake(iconX + iconWidth + 15, 0, 60, viewHeight);
            label.backgroundColor = [UIColor clearColor];
            label.tag = labelTag;
            [view addSubview:label];
        }
        
        // 设置图标
        UIImageView *icon = (UIImageView *)[view viewWithTag:iconTag];
        icon.image = [UIImage imageNamed:row==0?@"male.png":@"female.png"];
        
        // 设置文字
        UILabel *label = (UILabel *)[view viewWithTag:labelTag];
        label.text = row==0?@"":@"";
        
        return view;
    }
    #pragma mark 监听选中了某一行
    - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
        self.sex.text = row==0?@"":@"";
    }
    @end
    #import <UIKit/UIKit.h>
    @protocol KeyboardToolDelegate;
    
    typedef enum {
        kKeyboardToolButtonTypeNext, // 下一个按钮
        kKeyboardToolButtonTypePrevious, // 上一个按钮
        kKeyboardToolButtonTypeDone // 完成按钮
    } KeyboardToolButtonType;
    
    @interface KeyboardTool : UIToolbar
    // 按钮
    @property (nonatomic, readonly) IBOutlet UIBarButtonItem *nextBtn;
    @property (nonatomic, readonly) IBOutlet UIBarButtonItem *previousBtn;
    @property (nonatomic, readonly) IBOutlet UIBarButtonItem *doneBtn;
    
    // 代理一般用assign策略
    @property (nonatomic, assign) id<KeyboardToolDelegate> delegate;
    
    + (id)keyboardTool;
    
    // 这里写成 - 是为了能在xib中连线
    - (IBAction)next;
    - (IBAction)previous;
    - (IBAction)done;
    @end
    
    @protocol KeyboardToolDelegate <NSObject>
    - (void)keyboardTool:(KeyboardTool *)tool buttonClick:(KeyboardToolButtonType)type;
    @end
    
    
    #import "KeyboardTool.h"
    
    @implementation KeyboardTool
    
    @synthesize delegate = _toolDelegate;
    
    #pragma mark 从xib文件中初始化一个KeyboardTool
    + (id)keyboardTool {
        // owner可以传KeyboardTool这个类
        // 点击"下一个"按钮的时候,要调用owner的next方法
        
        NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"keyboardTool" owner:nil options:nil];
        
        // 返回初始化完毕的KeyboardTool
        return [array lastObject];
    }
    
    #pragma mark - 按钮点击
    - (void)next {
        if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonClick:)]) {
            [_toolDelegate keyboardTool:self buttonClick:kKeyboardToolButtonTypeNext];
        }
    }
    
    - (void)previous {
        if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonClick:)]) {
            [_toolDelegate keyboardTool:self buttonClick:kKeyboardToolButtonTypePrevious];
        }
    }
    
    - (void)done {
        if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonClick:)]) {
            [_toolDelegate keyboardTool:self buttonClick:kKeyboardToolButtonTypeDone];
        }
    }
    @end
  • 相关阅读:
    MQTT 协议快速体验
    vue学习之动态绑定样式
    vue学习之过滤器Filters
    ES6学习之async和await
    vue学习之组件命名
    vue学习之props验证
    vue学习之vite
    使用less
    Js学习之ES6模块化
    webpack通俗易懂入门篇
  • 原文地址:https://www.cnblogs.com/gcb999/p/3145917.html
Copyright © 2020-2023  润新知