鍵盤事件
- 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];
}
繼承關系.png
屬性(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
};
Paste_Image.png
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;
}
}
}