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 + ); if (distance < ) { // 说明键盘挡住了文本框
[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 -;
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 -;
_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 ;
}
#pragma mark 第component列有多少行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
return ;
} #pragma mark - UIPickerView代理方法
// picker的每一行要保证结构是一样
// reusingView:(UIView *)view就是缓存池中的可循环利用的View
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view { static int iconTag = ;
static int labelTag = ; // 如果没有可循环利用的View
if (view == nil) {
view = [[[UIView alloc] init] autorelease];
CGFloat viewHeight = ;
view.bounds = CGRectMake(, , , viewHeight); // 添加ImageView
UIImageView *icon = [[[UIImageView alloc] init] autorelease];
CGFloat iconX = ;
CGFloat iconWidth = ;
CGFloat iconHeight = ;
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 + , , , viewHeight);
label.backgroundColor = [UIColor clearColor];
label.tag = labelTag;
[view addSubview:label];
} // 设置图标
UIImageView *icon = (UIImageView *)[view viewWithTag:iconTag];
icon.image = [UIImage imageNamed:row==?@"male.png":@"female.png"]; // 设置文字
UILabel *label = (UILabel *)[view viewWithTag:labelTag];
label.text = row==?@"男":@"女"; return view;
}
#pragma mark 监听选中了某一行
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
self.sex.text = row==?@"男":@"女";
}
@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

ios中键盘处理源码的更多相关文章

  1. (转)Spring对注解(Annotation)处理源码分析1——扫描和读取Bean定义

    1.从Spring2.0以后的版本中,Spring也引入了基于注解(Annotation)方式的配置,注解(Annotation)是JDK1.5中引入的一个新特性,用于简化Bean的配置,某些场合可以 ...

  2. ios 中生成二维码和相册中识别二维码

    iOS 使用CIDetector扫描相册二维码.原生扫描 原生扫描 iOS7之后,AVFoundation让我们终于可以使用原生扫描进行扫码了(二维码与条码皆可)AVFoundation可以让我们从设 ...

  3. 【swift】ios中生成二维码

    ios开发中可以自己代码生成二维码,需要使用到一个框架 CoreImage CoreImage框架可以做滤镜,Gif动图,二维码等 先看效果图 下面直接贴上代码(OC也是下面一样的流程) func c ...

  4. iOS中 扫描二维码/生成二维码详解 韩俊强的博客

    最近大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 指示根视图: se ...

  5. IOS中键盘隐藏几种方式

    在ios开发中,经常需要输入信息.输入信息有两种方式: UITextField和UITextView.信息输入完成后,需要隐藏键盘,下面为大家介绍几种隐藏键盘的方式. <一> 点击键盘上的 ...

  6. iOS中 扫描二维码/生成二维码具体解释 韩俊强的博客

    近期大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang  新浪微博 指示根视图: se ...

  7. iOS中键盘的收起

    在UIViewController中收起键盘,除了调用相应控件的resignFirstResponder方法之外,还有另外三种方法: 重载UIViewController中的touchesBegin方 ...

  8. ASP.NET Core静态文件处理源码探究

    前言     静态文件(如 HTML.CSS.图像和 JavaScript)等是Web程序的重要组成部分.传统的ASP.NET项目一般都是部署在IIS上,IIS是一个功能非常强大的服务器平台,可以直接 ...

  9. H5页面IOS中键盘弹出导致点击错位的问题

    IOS在点击输入框弹出键盘  键盘回缩 后 定位没有相应改变  还有  textarea 也会弹出键盘 $("input").blur(function() { console.l ...

随机推荐

  1. jquery.cookie 使用方法

    一个轻量级的cookie 插件,可以读取.写入.删除 cookie. jquery.cookie.js 的配置 首先包含jQuery的库文件,在后面包含 jquery.cookie.js 的库文件. ...

  2. 深挖android low memory killer

    对于PC来说,内存是至关重要.如果某个程序发生了内存泄漏,那么一般情况下系统就会将其进程Kill掉.Linux中使用一种名称为OOM(Out Of Memory,内存不足)的机制来完成这个任务,该机制 ...

  3. 手动建库时一个错误:Error accessing PRODUCT_USER_PROFILE

    首先感谢前辈的文章:http://space.itpub.net/14184018/viewspace-691502 手动创建数据库完成后,创建新用户,并用新用户登陆到数据库时,报错如下: SYS@ ...

  4. ZooKeeper 了解

  5. Spring中的代理模式

    代理模式 所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用. 代理模式是一种 ...

  6. php 传变量到 js 文件

    php 传变量到 js 文件 // 传变量到js $oncj="taocanonc(".$i.",".$alli.",".$row1[mon ...

  7. Android 从 Android 本地图库选择多个图片

    原文地址 本文说明如何从 Android 本地图库选择多个图片.作者考虑很多解决方案. 演示从 Android 本地图库选择多个图片,有两个方法可以实现从图库中选择多个图片: 用 Intent 获取多 ...

  8. 关于 URL 编码及 JavaScript 编码函数【转载+整理】

    原文地址:http://www.ruanyifeng.com/blog/2010/02/url_encoding.html 本文内容 引入 环境 测试 JavaScript 编码函数   引入 URL ...

  9. Solidworks如何把装配体做成单个零件

    先把装配体另存为IGS格式   再把IGS打开之后另存为SLDPRT格式(打开IGS需要比较长的时间,中途会弹出提示,而且IGS文件体积也比较大)   另存为SLDPRT之后体积就很小了       ...

  10. 牛客网-《剑指offer》-从尾到头打印链表

    题目:http://www.nowcoder.com/practice/d0267f7f55b3412ba93bd35cfa8e8035 C++ /** * struct ListNode { * i ...