ios中键盘处理源码
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中键盘处理源码的更多相关文章
- (转)Spring对注解(Annotation)处理源码分析1——扫描和读取Bean定义
1.从Spring2.0以后的版本中,Spring也引入了基于注解(Annotation)方式的配置,注解(Annotation)是JDK1.5中引入的一个新特性,用于简化Bean的配置,某些场合可以 ...
- ios 中生成二维码和相册中识别二维码
iOS 使用CIDetector扫描相册二维码.原生扫描 原生扫描 iOS7之后,AVFoundation让我们终于可以使用原生扫描进行扫码了(二维码与条码皆可)AVFoundation可以让我们从设 ...
- 【swift】ios中生成二维码
ios开发中可以自己代码生成二维码,需要使用到一个框架 CoreImage CoreImage框架可以做滤镜,Gif动图,二维码等 先看效果图 下面直接贴上代码(OC也是下面一样的流程) func c ...
- iOS中 扫描二维码/生成二维码详解 韩俊强的博客
最近大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang 新浪微博 指示根视图: se ...
- IOS中键盘隐藏几种方式
在ios开发中,经常需要输入信息.输入信息有两种方式: UITextField和UITextView.信息输入完成后,需要隐藏键盘,下面为大家介绍几种隐藏键盘的方式. <一> 点击键盘上的 ...
- iOS中 扫描二维码/生成二维码具体解释 韩俊强的博客
近期大家总是问我有没有关于二维码的demo,为了满足大家的需求,特此研究了一番,希望能帮到大家! 每日更新关注:http://weibo.com/hanjunqiang 新浪微博 指示根视图: se ...
- iOS中键盘的收起
在UIViewController中收起键盘,除了调用相应控件的resignFirstResponder方法之外,还有另外三种方法: 重载UIViewController中的touchesBegin方 ...
- ASP.NET Core静态文件处理源码探究
前言 静态文件(如 HTML.CSS.图像和 JavaScript)等是Web程序的重要组成部分.传统的ASP.NET项目一般都是部署在IIS上,IIS是一个功能非常强大的服务器平台,可以直接 ...
- H5页面IOS中键盘弹出导致点击错位的问题
IOS在点击输入框弹出键盘 键盘回缩 后 定位没有相应改变 还有 textarea 也会弹出键盘 $("input").blur(function() { console.l ...
随机推荐
- WCF Ajax Json的应用
WCF Ajax 的应用网上实际上有很多, 如: Ajax与Wcf交互-JSON jQuery调用WCF服务传递JSON对象 WCF以Json格式返回对象,客户端以JS调用显示 关于SoapUI的介绍 ...
- 企业级搜索引擎Solr 第三章 索引数据(Indexing Data)[1] (转)
Index Data Author: David Smiley Eric Pugh 译者:Koala++ / 屈伟 在这一章中我们将了解如何将数据传入Solr.这个传入的过程称之为索引,尽管中间还包含 ...
- 为什么你作为一个.NET的程序员工资那么低?(转)
最近看到很多抱怨贴,也许有一定的道理,但是你想过没,为什么大部分.NET程序员工资相对低?我个人是这么看的: 大批半罐子水的程序员,永远被局限在.NET的原始的小圈圈里.前端不会(你放弃了一项很重要的 ...
- 【大数据】MongoDB安装(转)
https://note.youdao.com/share/?id=40be7f77434910e8860c5fd1ef5d24fe&type=note#/ MongoDB安装 环境 Cent ...
- MySQL 常用函数之——substr()
substr()函数是用来截取数据库某一列字段中的一部分 常用的方式是: SBUSTR(str,pos); 就是从pos开始的位置,一直截取到最后. SUBSTR(str,pos,len); 这种表示 ...
- nginx location 匹配的规则
nginx 的配置文件中, server里面的location 的配置项的理解: server { listen 24010; client_max_body_size 30M; location = ...
- 使用 GNU Libtool 创建库
这篇文档向大家介绍 GNU Libtool 的用途及基本使用方法,同时描述如何结合 GNU Autoconf 和 Automake 来使用 Libtool. 3 评论: 吴 小虎, 程序员, 天用唯勤 ...
- THINKPHP 错误:Undefined class constant 'MYSQL_ATTR_INIT_COMMAND'
最近公司同事将我之前使用Thinkphp开发的一个项目从香港迁移到国内阿里云服务器上去,结果网站所有地址打开全部一片空白 跟同事确认了PHP版本,Mysql版本等都是跟迁移前的配置一样的,最终经过我查 ...
- 教育单元测试mock框架优化之路(上)
转载:https://sq.163yun.com/blog/article/169561874192850944 众所周知,mock对于单元测试,尤其是基于spring容器的单元测试,是非常重要的.它 ...
- 前端特效: 使用CSS生成的闪光照相机效果
使用纯CSS生成的照相机效果, 相关CSS代码如下: .container { position: absolute; top: 50%; left: 50%; -webkit-transform: ...