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 ...
随机推荐
- Direct I/O,Synchronous I/O的概念
Direct I/O概念: Direct I/O is a way to avoid entire caching layer in the kernel and send the I/O direc ...
- jQuery-append添加元素click无效
很久没有使用jQuery,做项目的时候遇到一个小问题就是网页加载之后的append的元素是可以执行click事件,网页加载完成之后的,再次append的元素不执行click事件,简单的通过ul模拟一下 ...
- AS 功能 设置 SDK AVD 简介 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- LigerUI之Grid使用详解(一)——显示数据
目录: 一.概述 二.Grid使用步骤 三.使用Grid展示数据 四.源码下载 一.概述 在开发web信息管理系统时,使用Web前端框架可以帮助我们快速搭建一组风格统一的界面效果,而且能够解决大多数浏 ...
- Android -- 系统和自定义Notification
Notification是一种让你的应用程序在不使用Activity的情况下警示用户,Notification是看不见的程序组件警示用户有需要注意的事件发生的最好途径. 作为UI部分,Notifica ...
- 理解TensorFlow的Queue
https://www.jianshu.com/p/d063804fb272 这篇文章来说说TensorFlow里与Queue有关的概念和用法. 其实概念只有三个: Queue是TF队列和缓存机制的实 ...
- Python机器学习实践与Kaggle实战(转)
https://mlnote.wordpress.com/2015/12/16/python%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%AE%9E%E8%B7%B5 ...
- 成为Linux内核高手的四个方法
首页 最新文章 资讯 程序员 设计 IT技术 创业 在国外 营销 趣文 特别分享 更多 > - Navigation -首页最新文章资讯程序员设计IT技术- Java & Android ...
- 结构体指针之 段错误 具体解释(segmentation fault)
一个网友问了我一个问题.一个C程序执行出现了段错误,这个问题非常好.非常多刚開始学习的人都easy犯这个错误,详细代码例如以下: watermark/2/text/aHR0cDovL2Jsb2cuY3 ...
- Linux环境下网络编程杂谈《转》
今天我们说说“Pre-网络编程”.内容比较杂,但都是在做网络应用程序开发过程中经常要遇到的问题. 一.大端.小端和网络字节序 小端字节序:little-endian,将低字节存放在内存的起始地址: 大 ...