1:先分別設置各個文本框的鍵盤類型(inputview)-->在特定鍵盤中textediting中禁用輸入。緩存
2:而後遞歸綁定各個鍵盤的工具條(inputaccessview).
而且個各個控件綁定有順序的tagide
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