最終效果圖:
Main.storyboard
KeyboardTool.xib
KeyboardTool.h
// KeyboardTool.h
// 鍵盤處理
// Created by beyond on 14-8-24.
// Copyright (c) 2014年 com.beyond. All rights reserved.
#import <UIKit/UIKit.h>
@protocol KeyboardToolDelegate;
typedef enum {
kKeyboardToolButtonTypeNext, // 下一個按鈕
kKeyboardToolButtonTypePrevious, // 上一個按鈕
kKeyboardToolButtonTypeDone // 完成按鈕
} KeyboardToolButtonType;
@interface KeyboardTool : UIToolbar
// 上一個按鈕控件
@property (nonatomic, weak) IBOutlet UIBarButtonItem *previousBtn;
// 下一個按鈕控件
@property (nonatomic, weak) IBOutlet UIBarButtonItem *nextBtn;
// 完成按鈕控件
@property (nonatomic, weak) IBOutlet UIBarButtonItem *doneBtn;
// 代理一般用weak,同時,避免與預設的繼承的delegate沖突
@property (nonatomic, weak) id<KeyboardToolDelegate> toolDelegate;
// 類方法 傳回一個執行個體對象
+ (id)keyboardTool;
// 監聽工具條上 三個按鈕的點選 事件
- (IBAction)previousBtnClicked;
- (IBAction)nextBtnClicked;
- (IBAction)doneBtnClicked;
@end
KeyboardTool.m
// KeyboardTool.m
// 鍵盤處理
// Created by beyond on 14-8-24.
// Copyright (c) 2014年 com.beyond. All rights reserved.
#import "KeyboardTool.h"
#import "KeyboardToolDelegate.h"
@implementation KeyboardTool
// 類方法,從xib檔案中初始化一個KeyboardTool
+ (id)keyboardTool {
// owner可以傳KeyboardTool這個類
// 點選"下一個"按鈕的時候,要調用owner的next方法
NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"keyboardTool" owner:nil options:nil];
// 傳回初始化完畢的KeyboardTool對象
return array[0];
}
#pragma mark - 點選事件
// 點選了上一個按鈕
- (void)previousBtnClicked {
if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonType:)]) {
// 告訴代理,點選的是上一個按鈕
[_toolDelegate keyboardTool:self buttonType:kKeyboardToolButtonTypePrevious];
}
}
// 點選了下一個按鈕
- (void)nextBtnClicked {
if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonType:)]) {
// 告訴代理,點選的是下一個按鈕
[_toolDelegate keyboardTool:self buttonType:kKeyboardToolButtonTypeNext];
}
}
// 點選了完成按鈕
- (void)doneBtnClicked {
if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonType:)]) {
// 告訴代理,點選的是完成按鈕
[_toolDelegate keyboardTool:self buttonType:kKeyboardToolButtonTypeDone];
}
}
@end
KeyboardToolDelegate.h
//
// KeyboardToolDelegate.h
// 22_鍵盤綜合案例
//
// Created by beyond on 14-8-24.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//
#import <Foundation/Foundation.h>
@class KeyboardTool;
@protocol KeyboardToolDelegate <NSObject>
- (void)keyboardTool:(KeyboardTool *)tool buttonType:(KeyboardToolButtonType)type;
@end
BeyondViewController.h
//
// BeyondViewController.h
// 22_鍵盤綜合案例
//
// Created by beyond on 14-8-24.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "KeyboardTool.h"
#import "KeyboardToolDelegate.h"
@interface BeyondViewController : UIViewController <UITextFieldDelegate, UIPickerViewDataSource, UIPickerViewDelegate, KeyboardToolDelegate>
// 生日輸入框
@property (weak, nonatomic) IBOutlet UITextField *birthdayTextField;
// 城市輸入框
@property (weak, nonatomic) IBOutlet UITextField *cityTextField;
@end
BeyondViewController.m
//
// BeyondViewController.m
// 22_鍵盤綜合案例
//
// Created by beyond on 14-8-24.
// Copyright (c) 2014年 com.beyond. All rights reserved.
//
#import "BeyondViewController.h"
@interface BeyondViewController ()
// 所有省名組成的數組
@property (nonatomic, strong) NSArray *provinceNameArr;
// 字典:省名key---value城市名組成的數組
@property (nonatomic, strong) NSDictionary *provinceName_cities_Dict;
// 目前激活的活躍狀态的輸入框
@property (nonatomic, weak) UITextField *currentTextField;
// 鍵盤上的工具條
@property (nonatomic, weak) KeyboardTool *tool;
// 所有輸入框控件 組成的數組
@property (nonatomic, strong) NSMutableArray *allTextFields;
@end
@implementation BeyondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.allTextFields = [NSMutableArray array];
// 類方法,執行個體化一個KeyboardTool對象
self.tool = [KeyboardTool keyboardTool];
self.tool.backgroundColor = [UIColor clearColor];
self.tool.barTintColor = [UIColor lightGrayColor];
// 并且設定鍵盤工具的代理為目前控制器,用于接收其内部的btn點選事件,感覺btnType
self.tool.toolDelegate = self;
// 1.設定所有文本框的鍵盤工具條 都是 自定義的KeyboardTool
for (UITextField *field in self.view.subviews)
{
// 如果不是文本輸入框,繼續
if (![field isKindOfClass:[UITextField class]]) continue;
// 每一個文本輸入框的鍵盤工具都是它...
field.inputAccessoryView = self.tool;
// 數組儲存所有的文本輸入框控件,後面要用到
[self.allTextFields addObject:field];
// 設定每個文本輸入框的代理都是目前控制器
field.delegate = self;
}
// 2.為生日輸入框,設定鍵盤為DatePicker
[self setInputViewForBirthdayTextField];
// 3.為城市輸入框,設定鍵盤為DatePicker
[self setInputViewForCityTextField];
// 4.加載所有的資料
[self loadAllData];
}
// 2.為生日輸入框,設定鍵盤為DatePicker
- (void)setInputViewForBirthdayTextField
{
// 設定生日的鍵盤(不用設定寬高和位置)
UIDatePicker *datePicker = [[UIDatePicker alloc] init];
// 設定區域為中國簡體中文
datePicker.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"];
// 模式為:隻顯示日期
datePicker.datePickerMode = UIDatePickerModeDate;
// 監聽datePicker的值改事件
[datePicker addTarget:self action:@selector(datePickerValueChangeed:) forControlEvents:UIControlEventValueChanged];
// 設定其為生日輸入框的view
self.birthdayTextField.inputView = datePicker;
}
// 3.為城市輸入框,設定鍵盤為DatePicker
- (void)setInputViewForCityTextField
{
// 設定城市的鍵盤
UIPickerView *picker = [[UIPickerView alloc] init];
// 設定資料源和代理
picker.dataSource = self;
picker.delegate = self;
// 顯示訓示器
picker.showsSelectionIndicator = YES;
// 設定其為城市輸入框的view
self.cityTextField.inputView = picker;
}
// 4.加載所有的資料
- (void)loadAllData
{
// 加載省份資料
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cities" ofType:@"plist"]];
// 所有以省名組成的數組
self.provinceNameArr = dict[@"provinces"];
// 字典,鍵是省名,值是城市名組成的數組
self.provinceName_cities_Dict = dict[@"cities"];
}
// 2.1監聽生日選擇控件的值改變事件,為生日輸入框指派
- (void)datePickerValueChangeed:(UIDatePicker *)picker
{
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd";
// 生日輸入框指派
self.birthdayTextField.text = [formatter stringFromDate:picker.date];
}
#pragma mark - PickerView資料源方法
// 一共多少列
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
// 第一列是省名,第二列是省名對應的城市數組
return 2;
}
// 每一列對應多少行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component == 0) {
// 傳回省名數組的長度
return self.provinceNameArr.count;
} else {
// 傳回第1列 目前選中的行号
NSUInteger rowNum = [pickerView selectedRowInComponent:0];
// 先從省名數組,取出對應的省名
NSString *pName = self.provinceNameArr[rowNum];
// 再從字典中,通過省名,擷取城市數組,并傳回其長度
NSArray *cityArr = self.provinceName_cities_Dict[pName];
return cityArr.count;
}
}
// 每列每行顯示什麼資料
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if (component == 0) {
//前一列,顯示省名
return self.provinceNameArr[row];
} else {
// 傳回第1列 目前選中的行号
NSUInteger rowNum = [pickerView selectedRowInComponent:0];
// 先從省名數組,取出對應的省名
NSString *pName = self.provinceNameArr[rowNum];
// 再從字典中,通過省名,擷取城市數組,并傳回其長度
NSArray *cityArr = self.provinceName_cities_Dict[pName];
return cityArr[row];
}
}
// UIPickerView選中了某一行就會調用
- (void)pickerView:(UIPickerView *)pickerView
didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
// 重新整理後一列的資料,關聯效果
[pickerView reloadComponent:1];
NSUInteger pRowNum = [pickerView selectedRowInComponent:0];
// 先從省名數組,取出對應的省名
NSString *pName = self.provinceNameArr[pRowNum];
NSUInteger cRowNum = [pickerView selectedRowInComponent:1];
// 再從字典中,通過省名,擷取城市數組,并傳回其對應的城市名
NSArray *cityArr = self.provinceName_cities_Dict[pName];
NSString *cName = cityArr[cRowNum];
// 城市輸入框指派
self.cityTextField.text = [NSString stringWithFormat:@"%@ %@", pName, cName];
}
#pragma mark - 重點!!!!!!!!keyboardTool代理方法
- (void)keyboardTool:(KeyboardTool *)tool
buttonType:(KeyboardToolButtonType)type
{
if (type == kKeyboardToolButtonTypeDone) {
//當點選完成時,目前活動的輸入框,取消第一響應者,退出鍵盤
[self.currentTextField resignFirstResponder];
} else {
//先取出目前輸入框在輸入框數組中的索引,
NSUInteger index = [self.allTextFields indexOfObject:self.currentTextField];
if (type == kKeyboardToolButtonTypePrevious) {
//當點選上一個時,索引減1,
index--;
} else {
//當點選下一個時,索引加1,
index++;
}
// 取出對應索引的輸入框,成為即将成為的第一響應者,調出對應的鍵盤
UITextField *field = self.allTextFields[index];
[field becomeFirstResponder];
}
}
#pragma mark - 重點!!!!!!!UITextField代理方法
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
// 記住被激活的文本框,其他方法keyboardTool:buttonClick:中要用到
self.currentTextField = textField;
// 先取得本輸入框在所有輸入框組成的數組中的索引
NSUInteger index = [self.allTextFields indexOfObject:textField];
// 設定下一個按鈕的,是否可用
self.tool.nextBtn.enabled = index != self.allTextFields.count - 1;
// 設定上一個按鈕的,是否可用
self.tool.previousBtn.enabled = index != 0;
}
// 這個是 UITextField的一個委托方法!
// 利用這個委托 我們在打開鍵盤的時候,點選return 就可以關閉鍵盤了
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
// 結束所有編輯,退出所有鍵盤,并且傳回YES就可以
[self.view endEditing:YES];
return YES;
}
@end
資料源