ios中键盘处理源码
2013-06-20 14:17 甘超波 阅读(2957) 评论(2) 编辑 收藏 举报
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
目前我正在专注NLP,请立刻加微信/QQ号 546611623, 免费送你原创《NLP高级执行师》高清视频