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. [leetcode]Add Binary @ Python

    原题地址:https://oj.leetcode.com/problems/add-binary/ 题意: Given two binary strings, return their sum (al ...

  2. Word Ladder leetcode java

    题目: Given two words (start and end), and a dictionary, find the length of shortest transformation se ...

  3. ICTCLAS中的HMM人名识别

    http://www.hankcs.com/nlp/segment/ictclas-the-hmm-name-recognition.html 本文主要从代码的角度分析标注过程中的细节,理论谁都能说, ...

  4. java中两种发起POST请求,并接收返回的响应内容的方式  (转)

    http://xyz168000.blog.163.com/blog/static/21032308201162293625569/ 2.利用java自带的java.net.*包下提供的工具类 代码如 ...

  5. object-c 混编 调用C,C++接口

    xcode 支持 object-c 混编,在object-c 中调用c,c++接口 第一步 定义c语言 接口(File.c) #include <stdio.h> void printsB ...

  6. Java-JUC(十):线程按序交替执行

    问题: 有a.b.c三个线程,使得它们按照abc依次执行10次. 实现: package com.dx.juc.test; import java.util.concurrent.locks.Cond ...

  7. Mac下brew/memcached/nginx/iterm/zsh的安装

    brew  https://www.cnblogs.com/fireworld/p/8609190.html memcached https://blog.csdn.net/whereismatrix ...

  8. Cognos11中通过URL传参访问动态Report

    一.需求: 在浏览器输入一个URL,在URL后面加上参数就可以访问一个有提示值的报表?比如下面的报表 二.解决办法 Cognos  Model 查询主题设计层概要 Select * from [UCO ...

  9. (文档)流媒体资源 Streaming Assets

    Most assets in Unity are combined into the project when it is built. However, it is sometimes useful ...

  10. Xamarin/Mono IOS Limitations

    http://developer.xamarin.com/guides/ios/advanced_topics/limitations/ Since applications on the iPhon ...