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
原文地址:https://www.cnblogs.com/gcb999/p/3145917.html