最后效果图:





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. c#获取页面重定向url

    /// <summary> /// 获取页面重定向url /// </summary> /// <param name="url"></p ...

  2. 推断序列的端部的大小C规划

    概念 big-endian格式:高字节字符数据被存储在低地址.字数据的低字节存放在高地址. 小尾数格式:相较于大端存储格式,在小尾数格式.低地址存储在字数据的低字节.的是字数据的高字节. 如5A6C中 ...

  3. H.265/HEVC Codec 编解码 (MP4 和 TS)

    1. H.265/HEVC 播放器 1) VLC media player 2.1.3 (眼下不支持H.265 TS播放) 2)ffmpeg中的ffplay (如:ffplay  hevc.ts) 3 ...

  4. Visual Studio 2015使用EF6的ModelFirst模式添加实体数据模型缺少tt文件问题

    在看实体框架 (EF) 入门的时候,当按照样例做到ModelFirst的时候出问题了 这是使用vs2015新建的实体数据模型 这是官网样例 对比样例截图,会发现里面缺少.tt的文件.最重要的是最终代码 ...

  5. 渲染优化 之fixed与返回顶部 以及开启GPU Hack

    fixed元素,常见网站右侧出现一个返回顶部的按钮,滚动的时候,会发现返回顶部这个区域在不停的进行重绘,而返回顶部是position:fixed定位的.这也解释了为什么fixed定位是最耗性能的属性之 ...

  6. Mozilla5.0的含义

    mod=viewthread&tid=757008">http://www.lightnovel.cn/forum.php?mod=viewthread&tid=757 ...

  7. eclipse 在win7 64两个图标出现位操作系统无法锁定到任务栏或任务栏

    eclipse 在win7 64位操作系统无法锁定到任务栏或者任务栏上出现两个图标 解决的方法 eclipse在win7 64bit下无法锁定到任务栏问题(或是锁定后任务栏出现两个eclipse图标) ...

  8. vs2010中文简体版下载链接(含中文msdn)

    昨天朋友说vs2010中文版能够下载了,自己開始还不相信,正好周末,于是就下载了试一下 安装了果然是中文版,本来是msdn订阅用户才干够下载的,感谢上传的网友. 文件名称 cn_visual_stud ...

  9. Linux下is not in the sudoers file(转)

    用sudo时提示"xxx is not in the sudoers file. This incident will be reported.其中XXX是你的用户名,也就是你的用户名没有权 ...

  10. 介绍 Microservice

    介绍 Microservice 这篇文章转自我的 Github blog 一天我司招财猫姐(HR 大人)问我,你给我解释一下 Microservice 是什么吧.故成此文.一切都是从一个创业公司开始的 ...