最后效果图:





Main.storyboard

KeyboardTool.xib

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHJlX2VtaW5lbnQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

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, // 下一个button
kKeyboardToolButtonTypePrevious, // 上一个button
kKeyboardToolButtonTypeDone // 完毕button
} KeyboardToolButtonType; @interface KeyboardTool : UIToolbar // 上一个button控件
@property (nonatomic, weak) IBOutlet UIBarButtonItem *previousBtn; // 下一个button控件
@property (nonatomic, weak) IBOutlet UIBarButtonItem *nextBtn; // 完毕button控件
@property (nonatomic, weak) IBOutlet UIBarButtonItem *doneBtn; // 代理一般用weak,同一时候,避免与默认的继承的delegate冲突
@property (nonatomic, weak) id<KeyboardToolDelegate> toolDelegate; // 类方法 返回一个实例对象
+ (id)keyboardTool; // 监听工具条上 三个button的点击 事件
- (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这个类
// 点击"下一个"button的时候。要调用owner的next方法 NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"keyboardTool" owner:nil options:nil]; // 返回初始化完毕的KeyboardTool对象
return array[0];
}
#pragma mark - 点击事件
// 点击了上一个button
- (void)previousBtnClicked {
if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonType:)]) {
// 告诉代理,点击的是上一个button
[_toolDelegate keyboardTool:self buttonType:kKeyboardToolButtonTypePrevious];
}
}
// 点击了下一个button
- (void)nextBtnClicked {
if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonType:)]) {
// 告诉代理,点击的是下一个button
[_toolDelegate keyboardTool:self buttonType:kKeyboardToolButtonTypeNext];
}
} // 点击了完毕button
- (void)doneBtnClicked {
if ([_toolDelegate respondsToSelector:@selector(keyboardTool:buttonType:)]) {
// 告诉代理,点击的是完毕button
[_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

数据源

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcHJlX2VtaW5lbnQ=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">

版权声明:本文博主原创文章,博客,未经同意不得转载。

iOS_22自定义键盘工具栏的更多相关文章

  1. 【iOS自定义键盘及键盘切换】详解

    [iOS自定义键盘]详解 实现效果展示: 一.实现的协议方法代码 #import <UIKit/UIKit.h> //创建自定义键盘协议 @protocol XFG_KeyBoardDel ...

  2. ios 自定义键盘

    由于项目需要,需要自定义键盘.ios系统键盘会缓存键盘输入,并保存在系统目录下的文件里,并且是明文存储,存在帐号密码泄漏风险.在别人代码基础上修改了下,美化了下界面,去掉了字符输入,加了点击特效,截图 ...

  3. 自定义底部工具栏及顶部工具栏和Fragment配合使用demo

    首先简单的介绍下fragment,fragment是android3.0新增的概念,其中文意思是碎片,它与activity非常相似,用来在一个activity中描述一些行为或一部分用户界面.使用锁个f ...

  4. UI:自定义键盘的实现

    自定义我的封装键盘,并在试图控制器里对接 (解决多 输入框问题,把输入框存入到可变数组) @implementation AppDelegate - (BOOL)application:(UIAppl ...

  5. UI:登录窗的自定义键盘

    在创建一个自定义键盘的时候遇到的错误 //双重for循环,对于Button上的数字用二维数组 //    NSArray * butArr[4][3] = {@[@"1",@&qu ...

  6. 键盘工具栏的快速集成--HcCustomKeyboard

    源项目地址:HcCustomKeyboard HcCustomKeyboard是一个键盘工具栏控件: 效果: HcCustomKeyboard使用很方便: 三部: 添加控件->操作处理-> ...

  7. Vue2.0的变化 ,组件模板,生命周期,循环,自定义键盘指令,过滤器

    组件模板: 之前: <template> <h3>我是组件</h3><strong>我是加粗标签</strong> </templat ...

  8. vue.js之过滤器,自定义指令,自定义键盘信息以及监听数据变化

    一.监听数据变化 1.监听数据变化有两种,深度和浅度,形式如下: vm.$watch(name,fnCb); //浅度 vm.$watch(name,fnCb,{deep:true}); //深度监视 ...

  9. 雷林鹏分享:jQuery EasyUI 窗口 - 自定义窗口工具栏

    jQuery EasyUI 窗口 - 自定义窗口工具栏 默认情况下,窗口(window)有四个工具:collapsible.minimizable.maximizable 和 closable.比如我 ...

随机推荐

  1. 解决 U盘安装Windows Server 2012 R2 报错 Windows 无法打开所需的文件 Sources\install.wim

    报错原因: 使用UltraISO等软件刻录镜像时默认使用FAT32文件系统,该系统不支持大于4G的文件, 而Server 2012 R2的安装文件install.wim为5.12G,固安装失败. 解决 ...

  2. 全栈JavaScript之路(十七)HTML5 新增字符集属性

    HTML5 添加�了几个文档字符集属性. document.charset : 表示文档的实际使用的字符集. document.defaultCharset: 表示默认的字符集,跟浏览器以及操作系统设 ...

  3. UVa11488-Hyper Prefix Sets(trie树)

    H Hyper Prefix Sets Prefix goodness of a set string is length of longest common prefix*number of str ...

  4. DM8168 新三板系统启动

    DM8168从补丁到系统的新董事会开始折腾了20天,最终完成,高校是累的东西,导师只焊接机10一个BGA,其他人则手. 前段时间启动操作系统时,到了Starting Matrix GUI applic ...

  5. &lt;八&gt;阅读&lt;&lt;大话设计模式&gt;&gt;该模型的外观

    Facade模式其实很好理解,被表面的东西展示海报.内部的东西,你不知道(因为我们有一个好包).例如,外部和公司内部制度,5交互系统,此5互.那么第一种就是外部系统和5个系统都进行交互:另外一种就是做 ...

  6. ExtJS学习笔记:定义extjs类别

    类的定义 Ext.define('Cookbook.Vehicle', { Manufacturer: 'Aston Martin', Model: 'Vanquish', getDetails: f ...

  7. Cocos2d-x 手机游戏《疯狂的蝌蚪》资源 “开源” win32+安德鲁斯+iOS三合一

    郝萌主倾心贡献,尊重作者的劳动成果,转载请注明出处 From郝萌主. 假设文章对您有所帮助.欢迎给作者捐赠,支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载 ...

  8. IOS获得各种文档文件夹路径的方法

    iphone沙箱模型的有四个目录,各自是什么,永久数据存储一般放在什么位置.得到模拟器的路径的简单方式是什么. documents,tmp.app,Library. (NSHomeDirectory( ...

  9. .Net反编译实战

    原文:.Net反编译实战 当你面对一个已经部署好的网站,功能,性能都非常不给力的时候,你会怎么办? 当你尝试去了解这个网站业务逻辑,代码逻辑和数据库逻辑时却发现根本没有任何资料时你会怎么办? 当你准备 ...

  10. 设计模式(Facade)状态(注意事项)

    外观模式(Facade),子系统的一组接口提供一个一致的界面,该模式定义了一个高层次接口,这个接口使得这一子系统更加easy采用. 外观模式完美地体现了依赖反转原则,迪米特法则的想法,式之中的一个. ...