键盘事件
- UIKeyboardWillShowNotification
- UIKeyboardDidShowNotification
- UIKeyboardWillHideNotification
- UIKeyboardDidHideNotification
使用场景:
- 计算键盘的高度,调整UI布局
- 根据键盘显示隐藏执行UI的动画
使用方法
//注册事件
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
//接收事件
-(void)keyboardWillShow:(NSNotification*)notification{
NSDictionary*info=[notification userInfo];
CGSize kbSize=[[info objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue].size;
NSLog(@"keyboard changed, keyboard width = %f, height = %f",
kbSize.width,kbSize.height);
}
// NSNotification需要remove
-(void)viewDidUnload{
[superviewDidUnload];
[[NSNotificationCenter defaultCenter]removeObserver:self];
}
属性(Attributes)
UITextField的text属性与userInteractionEnabled共用。
textField.text = @"密码输入框"
// 输入框默认输入文本,有时需求UITextField只可显示不可编辑的,
// 此时起展示作用:用此属性设置需要显示的文本
// 然后设置UITextField不可交互textField.userInteractionEnabled = NO;
textField.userInteractionEnabled = NO;
placeholder设置字体颜色,大小
方法一:
textField.placeholder = @"密码输入框"; // 提示文本
[textField setValue:[UIColor colorWithRed:79/255.0f green:79/255.0f blue:79/255.0f alpha:0.5f] forKeyPath:@"_placeholderLabel.textColor"];
[textField setValue:[UIFont boldSystemFontOfSize:20] forKeyPath:@"_placeholderLabel.font"];
方法二:
textField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:@"密码输入框"
attributes:@{NSForegroundColorAttributeName: [UIColor colorWithRed:79/255.0f green:79/255.0f blue:79/255.0f alpha:0.5f],
NSFontAttributeName : [UIFont systemFontOfSize:20 weight:6],}];
边框
textField.borderStyle = UITextBorderStyleLine;
//效果如下图所示
typedef NS_ENUM(NSInteger, UITextBorderStyle) {
UITextBorderStyleNone,
UITextBorderStyleLine,
UITextBorderStyleBezel,
UITextBorderStyleRoundedRect
};
font属性
textField.font = [UIFont systemFontOfSize:14.0f];
textField.textColor = [UIColor redColor];
根据输入文字动态调整字体大小,需要设置一个最小字体大小
textField.adjustsFontSizeToFitWidth = YES;
textField.minimumFontSize = 10.0;//设置最小字体
设置输入内容的对其方式
textField.textAlignment = NSTextAlignmentLeft;
NSTextAlignmentLeft = 0, // Visually left aligned
#if TARGET_OS_IPHONE
NSTextAlignmentCenter = 1, // Visually centered
NSTextAlignmentRight = 2, // Visually right aligned
#else /* !TARGET_OS_IPHONE */
NSTextAlignmentRight = 1, // Visually right aligned
NSTextAlignmentCenter = 2, // Visually centered
#endif
NSTextAlignmentJustified = 3, // Fully-justified. The last line in a paragraph is natural-aligned.
NSTextAlignmentNatural = 4, // Indicates the default alignment for script
[textField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
[textField setContentHorizontalAlignment:UIControlContentHorizontalAlignmentRight];
UIControlContentVerticalAlignmentCenter = 0,
UIControlContentVerticalAlignmentTop = 1,
UIControlContentVerticalAlignmentBottom = 2,
UIControlContentVerticalAlignmentFill = 3,
UIControlContentHorizontalAlignmentCenter = 0,
UIControlContentHorizontalAlignmentLeft = 1,
UIControlContentHorizontalAlignmentRight = 2,
UIControlContentHorizontalAlignmentFill = 3,
与键盘相关的属性
textField.keyboardType = UIKeyboardTypeNumberPad; //设置键盘的样式
// typedef enum {
// UIKeyboardTypeDefault, 默认键盘,支持所有字符
// UIKeyboardTypeASCIICapable, 支持ASCII的默认键盘
// UIKeyboardTypeNumbersAndPunctuation, 标准电话键盘,支持+*#字符
// UIKeyboardTypeURL, URL键盘,支持.com按钮 只支持URL字符
// UIKeyboardTypeNumberPad, 数字键盘
// UIKeyboardTypePhonePad, 电话键盘
// UIKeyboardTypeNamePhonePad, 电话键盘,也支持输入人名
// UIKeyboardTypeEmailAddress, 用于输入电子 邮件地址的键盘
// UIKeyboardTypeDecimalPad, 数字键盘 有数字和小数点
// UIKeyboardTypeTwitter, 优化的键盘,方便输入@、#字符
// UIKeyboardTypeAlphabet = UIKeyboardTypeASCIICapable,
// } UIKeyboardType;
textField.autocapitalizationType = UITextAutocapitalizationTypeNone; //首字母是否自动大写
// typedef enum {
// UITextAutocapitalizationTypeNone, 不自动大写
// UITextAutocapitalizationTypeWords, 单词首字母大写
// UITextAutocapitalizationTypeSentences, 句子的首字母大写
// UITextAutocapitalizationTypeAllCharacters, 所有字母都大写
// } UITextAutocapitalizationType;
//
textField.keyboardAppearance=UIKeyboardAppearanceDefault; //键盘外观
// typedef enum {
// UIKeyboardAppearanceDefault, 默认外观,浅灰色
// UIKeyboardAppearanceAlert, 深灰 石墨色
// } UIReturnKeyType;
textField.returnKeyType =UIReturnKeyDone; //return键变成什么键
// typedef enum {
// UIReturnKeyDefault, 默认 灰色按钮,标有Return
// UIReturnKeyGo, 标有Go的蓝色按钮
// UIReturnKeyGoogle, 标有Google的蓝色按钮,用语搜索
// UIReturnKeyJoin, 标有Join的蓝色按钮
// UIReturnKeyNext, 标有Next的蓝色按钮
// UIReturnKeyRoute, 标有Route的蓝色按钮
// UIReturnKeySearch, 标有Search的蓝色按钮
// UIReturnKeySend, 标有Send的蓝色按钮
// UIReturnKeyYahoo, 标有Yahoo的蓝色按钮
// UIReturnKeyYahoo, 标有Yahoo的蓝色按钮
// UIReturnKeyEmergencyCall, 紧急呼叫按钮
// } UIReturnKeyType;
其他相关属性
// 以下几个属性通常不用,通常为自定义控件先设置一个UIView UIView上面再放UIImageview 和 UITextField,设置UIView的boder属性以满足要求。
leftView
Property
leftViewMode
Property
rightView
Property
rightViewMode
Property
清空输入框,常见于密码输入错入重新输入时会清空输入框。
textField.clearButtonMode = UITextFieldViewModeWhileEditing;// sets when the clear button shows up编辑的时候清空输入框
//clearsOnInsertion// whether inserting text replaces the previous contents.插入的时候清空输入框
// typedef NS_ENUM(NSInteger, UITextFieldViewMode) {
// UITextFieldViewModeNever,从不出现
// UITextFieldViewModeWhileEditing,编辑时出现
// UITextFieldViewModeUnlessEditing,除了编辑外都出现
// UITextFieldViewModeAlways 一直出现
// };
textField.autocorrectionType = UITextAutocorrectionTypeNo; //是否自动纠错
// typedef enum {
// UITextAutocorrectionTypeDefault, 默认
// UITextAutocorrectionTypeNo, 不自动纠错
// UITextAutocorrectionTypeYes, 自动纠错
// } UITextAutocorrectionType;
secureTextEntry 启用/禁用 UITextField对象的安全输入功能。如果设置成YES则类似于密码框内容将显示为圆点。
autocorrectionType 启用/禁用 UITextFieldUI想的拼写建议功能,根据用户输入错误的单词提供修改建议
autocapitalizationType 设置 UITextField的自动大写功能,
none:关闭大写功能
words: 单词
sentences: 句子
allcharacters:所有字母
四种类型
委托
委托在开发中使用也比较广泛,例如手机号码输入框,可以通过委托的shouldChangeCharactersInRange方法控制用户能且只能输入11位数字(例子讲解)。另外,开发中通常要求输入框内容输入后才让按钮可以点击。
委托的相关方法介绍
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
//返回一个BOOL值,指定是否循序文本字段开始编辑
return YES;
}
- (void)textFieldDidBeginEditing:(UITextField *)textField{
//开始编辑时触发,文本字段将成为first responder
}
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
//返回BOOL值,指定是否允许文本字段结束编辑,当编辑结束,文本字段会让出first responder
//要想在用户结束编辑时阻止文本字段消失,可以返回NO
//这对一些文本字段必须始终保持活跃状态的程序很有用,比如即时消息
return NO;
}
- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
//当用户使用自动更正功能,把输入的文字修改为推荐的文字时,就会调用这个方法。
//这对于想要加入撤销选项的应用程序特别有用
//可以跟踪字段内所做的最后一次修改,也可以对所有编辑做日志记录,用作审计用途。
//要防止文字被改变可以返回NO
//这个方法的参数中有一个NSRange对象,指明了被改变文字的位置,建议修改的文本也在其中
return YES;
}
- (BOOL)textFieldShouldClear:(UITextField *)textField{
//返回一个BOOL值指明是否允许根据用户请求清除内容
//可以设置在特定条件下才允许清除内容
return YES;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
//返回一个BOOL值,指明是否允许在按下回车键时结束编辑
//如果允许要调用resignFirstResponder 方法,这回导致结束编辑,而键盘会被收起[textField resignFirstResponder];
//查一下resign这个单词的意思就明白这个方法了
return YES;
}
需求一:如下图
1.phoneNumber输入框最多只能输入11位数字。
2.输入框有内容后按钮变成可点击状态否则为灰色。
CNNYRegisterInputView类为自定义的输入框
在.h文件里面定义好delegate协议如下
@protocol CNNYRegisterInputViewTextFieldDelegate <NSObject>
@optional
-(void)didTextFieldUnChange;
@optional
- (void)didTextFieldChange:(UITextField *)textField andText:(NSString *)text;
@end
@interface CNNYRegisterInputView : UIView<UITextFieldDelegate>
@property(weak, nonatomic) id<CNNYRegisterInputViewTextFieldDelegate> delegate;
@property (nonatomic,strong) UITextField *textfield;
@property (nonatomic,strong) UIImageView *leftView;
- (instancetype)InitInputViewWithImage:(NSString *)placeHolder andImage:(NSString *)imageUrl;
- (void)setMode:(CNRegisterInputMode)mode;
@end
在.m文件如下
//
// CNNYRegisterInputView.m
// cheniu_shop
//
// Created by brandonyum on 15/11/17.
// Copyright © 2015年 souche. All rights reserved.
//
#import "CNNYRegisterInputView.h"
#import <Masonry.h>
#import <UIColor+CNNHexColor.h>
#import "CNNYConstant.h"
static CGFloat const kMarginLfet = 16.0;
static NSString *const kBorderColorStr = @"#D1D1D1";
@interface CNNYRegisterInputView()
//@property (nonatomic,strong) UIImageView *leftView;
@property (nonatomic,strong) UIView *splitLine;
@end
@implementation CNNYRegisterInputView
- (instancetype)InitInputViewWithImage:(NSString *)placeHolder andImage:(NSString *)imageUrl{
if (self == [super init]) {
[self addSubview:self.textfield];
[self addSubview:self.leftView];
[self addSubview:self.splitLine];
[self Constraints];
[self.textfield setPlaceholder:CNNShopLoc(placeHolder)];
[self.textfield setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
[self.leftView setImage:[UIImage imageNamed:imageUrl]];
[self.layer setBorderColor:[UIColor cnn_colorWithHexString:kBorderColorStr].CGColor];
[self.layer setBorderWidth:0.5];
self.layer.cornerRadius = 8;
[self setBackgroundColor:[UIColor whiteColor]];
}
return self;
}
- (instancetype)init{
self = [super init];
if (self) {
[self addSubview:self.textfield];
[self addSubview:self.leftView];
[self addSubview:self.splitLine];
[self Constraints];
[self.layer setBorderColor:[UIColor cnn_colorWithHexString:kBorderColorStr].CGColor];
[self.layer setBorderWidth:0.5];
[self setBackgroundColor:[UIColor whiteColor]];
}
return self;
}
- (void)Constraints{
__weak typeof(self) weakSelf = self;
[self.leftView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(weakSelf.mas_left).offset(kMarginLfet);
make.top.bottom.equalTo(weakSelf);
make.width.equalTo(@(18.0));
}];
[self.splitLine mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(weakSelf.leftView.mas_right).offset(8.0);
make.top.equalTo(weakSelf).offset(12.0);
make.bottom.equalTo(weakSelf).offset(-12.0);
make.width.equalTo(@(0.3));
}];
[self.textfield mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(weakSelf.splitLine.mas_right).offset(8.0);
make.top.bottom.equalTo(weakSelf);
make.right.equalTo(weakSelf.mas_right).offset(-kMarginLfet);
}];
}
- (UIView *)splitLine{
if (!_splitLine) {
_splitLine = [[UIView alloc]init];
[_splitLine setBackgroundColor:[UIColor colorWithRed:181/255.0f green:181/255.0f blue:182/255.0f alpha:0.4]];
}
return _splitLine;
}
- (UITextField *)textfield{
if (!_textfield) {
_textfield = [[UITextField alloc]init];
[_textfield setFont:[UIFont systemFontOfSize:16.0]];
[_textfield setTextColor:[UIColor cnn_colorWithHexString:@"#808080"]];
[_textfield setClearButtonMode:UITextFieldViewModeWhileEditing];
[_textfield setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];
}
return _textfield;
}
- (UIImageView *)leftView{
if (!_leftView) {
_leftView = [[UIImageView alloc]init];
[_leftView setContentMode:UIViewContentModeCenter];
}
return _leftView;
}
//实现UITextField的委托协议
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSMutableString *text = [NSMutableString stringWithString:textField.text];
[text replaceCharactersInRange:range withString:string];
if (text.length > 0) {
//在输入框不为空的时候用定义好的协议发送通知,更新UI
if ([self.delegate respondsToSelector:@selector(didTextFieldChange:andText:)]) {
[self.delegate didTextFieldChange:textField andText:text];
}
}else{
//在输入框delete为空的时候用定义好的协议发送通知,更新UI
if ([self.delegate respondsToSelector:@selector(didTextFieldUnChange)]) {
[self.delegate didTextFieldUnChange];
}
}
//限制textField的长度不超过11位
if (text.length > 11) {
return NO;
}else{
return YES;
}
}
- (void)setMode:(CNRegisterInputMode)mode{
if (mode == CNRegisterInputModePhone) {
[_textfield setKeyboardType:UIKeyboardTypeNumberPad];
[_textfield setSecureTextEntry:NO];
}else{
[_textfield setKeyboardType:UIKeyboardTypeDefault];
[_textfield setSecureTextEntry:YES];
}
}
@end
需求优化,
上面代码中shouldChangeCharactersInRange
方法仅仅只是判断了text.length
的长度,大于指定长度假设为11位,大于11后return NO
。
- 思考1:用户复制粘贴怎么办。像微博那种限制140字,如果用户复制了200字到输入框中,这样限制用户输入长度就无效了。
- 思考2:用户输入了11位后,发现前面输错了,怎么办。现在已经是
return NO
了,发现根本无法更改。
解决示例代码:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
NSString *minValue = [self.field.valueRange valueForKey:min];
NSString *maxValue = [self.field.valueRange valueForKey:max];
//解决问题2,删除按钮,确认等按钮其长度为0,所以判断当输入长度为0的时候让按钮有效返回YES。
if (string.length == 0) {
return YES;
}
if (textField.tag == 2) {
if (string.length +range.location <= maxValue.length ) {
return YES;
}else{
return NO;
}
}else{
if (string.length + range.location > minValue.length) {
return NO;
}else{
return YES;
}
}
}