UITextfield

#import "ViewController.h"
@interface ViewController ()<UITextFieldDelegate>
@property (nonatomic, strong) UIView  * containerView;//背景View
@property (nonatomic, assign) CGFloat   originalY;//原始縱座標
@property (nonatomic, assign) CGFloat   containerViewHeight;//原始高度

@property (nonatomic, strong) UITextField * account;//賬號輸入框
@property (nonatomic, strong) UITextField * password;//密碼輸入框
@property (nonatomic, strong) UIButton    * commitButton;//提交按鈕
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self creatBgView];
    
    [self createOneAccountView];
    
    [self createOnePasswordView];
    
    [self createOneButton];

    [self registerKeyboardNotification];
   
}

#pragma mark - 創建一個背景View
-(void)creatBgView{
    UIView * containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 280, 300)];
    self.containerView = containerView;
    containerView.backgroundColor = [UIColor darkGrayColor];
    containerView.center = self.view.center;
    [self.view addSubview:containerView];
    
    //記錄下container的原始縱座標和高度 這一步很關鍵後面後用到這裏的數據
    CGFloat originalY = self.containerView.frame.origin.y;
    self.originalY = originalY;
    
    CGFloat containerViewHeight    = self.containerView.frame.size.height;
    self.containerViewHeight = containerViewHeight;
}


#pragma mark - 創建一個賬號輸入框
-(void)createOneAccountView{
    UITextField * account = [[UITextField alloc] initWithFrame:CGRectMake(40, 80, 200, 40)];
    self.account = account;
    self.account.delegate = self;
//一、顯示相關設置
    //1、背景顏色設置
    account.backgroundColor = [UIColor redColor];
    
    //2、背景圖片設置
    account.background = [UIImage imageNamed:@""];
    
    /*
     3、邊框樣式設置
     UITextBorderStyleNone,       //無邊框效果
     UITextBorderStyleLine,       //黑色實線邊框
     UITextBorderStyleBezel,      //灰色實線邊框
     UITextBorderStyleRoundedRect //圓角矩形邊框
     */
    account.borderStyle = UITextBorderStyleRoundedRect;
    
    //4、左側頭視圖設置
    //左側頭試圖 x y值無效果
    UIView *leftView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 10, 40)];
    //clearColor 將衍射設爲透明顏色 可用來調節光標的位置
    leftView.backgroundColor = [UIColor blueColor];
    //設置什麼時候顯示
    account.leftViewMode = UITextFieldViewModeAlways;
    account.leftView = leftView;
    
    
    //5、右側頭視圖設置
    //右側頭視圖 x y值無效果
    UIView *rightView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 10, 40)];
    //設置顏色
    rightView.backgroundColor = [UIColor blueColor];
    //設置什麼時候顯示
    account.rightViewMode = UITextFieldViewModeAlways;
    account.rightView = rightView;


    
//二、文字設置
    //1、佔位文字設置
    account.placeholder = @"請輸入賬號";
    
    //2、內容設置,比如設置自動填充。
    account.text = @"內容設置";
    
    //3、內容是否以密文形式顯示
//    account.secureTextEntry = YES;
    
    //4、重新編輯時是否自動清除內容
    account.clearsOnBeginEditing = YES;
    
    /*
     5、刪除按鈕顯示設置
     UITextFieldViewModeNever,              //清除按鈕不可見
     UITextFieldViewModeWhileEditing,       //編輯內容時清除按鈕可見
     UITextFieldViewModeUnlessEditing,      //除了編輯之外,清除按鈕都可見
     UITextFieldViewModeAlways              //清除按鈕一直可見
     */
    //疑問1:UITextFieldViewModeUnlessEditing爲什麼設置這個沒有效果
    account.clearButtonMode = UITextFieldViewModeWhileEditing;
    
    //6、這兩個屬性配合使用,一個用來設置字體自動適應,一個用來設置允許最小的字體
    account.adjustsFontSizeToFitWidth = YES;
    account.minimumFontSize = 10;
    
    /*
     7、字母大小寫自動轉換
     UITextAutocapitalizationTypeNone,              //無自動轉換
     UITextAutocapitalizationTypeWords,             //首字母自動轉大寫
     UITextAutocapitalizationTypeSentences,         //每個句子的首字母轉大寫
     UITextAutocapitalizationTypeAllCharacters,     //所有字母自動轉大寫
     */
    account.autocapitalizationType = UITextAutocapitalizationTypeSentences;
    
    
    /*
     8、輸入文字時自動更正提示框
     UITextAutocorrectionTypeDefault,
     UITextAutocorrectionTypeNo,
     UITextAutocorrectionTypeYes,
     */
    account.autocorrectionType = UITextAutocorrectionTypeDefault;
    
    //9、響應者問題 成爲第一響應者 程序進來的時候,光標會在這個輸入框內閃爍,也就是已經來到了DidBeginEditing狀態
    //設置了代理的話,這個方法會使程序調用 1、2、這兩個代理方法
//    [account becomeFirstResponder];
    
    //10、註銷第一響應者會結束編輯
    //這個方法會使輸入框結束編輯,設置了代理的話,這個方法會使程序調用4、5、這個兩個代理方法
    //一般在點擊return鍵的時候會調用這個方法來結束輸入框的編輯狀態
//    [account resignFirstResponder];
    
    
//三、鍵盤設置相關
    //1、設置不同的鍵盤類型
    account.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
    
    //2、返回鍵的樣式
    account.returnKeyType = UIReturnKeyGo;
    //設爲yes時 只有當輸入內容時return鍵纔可用
    //設爲no時,什麼時候都可用,不會鎖定
//    account.enablesReturnKeyAutomatically = YES;
    
    //3、鍵盤顯示樣式
    account.keyboardAppearance = UIKeyboardAppearanceDark;
    
    //4、自定義鍵盤
    UIView *keyView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 100)];
    keyView.backgroundColor = [UIColor redColor];
    account.inputView = keyView;
    
    //5、自定義二級鍵盤
    UIView *secondView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 40)];
    secondView.backgroundColor = [UIColor greenColor];
//    account.inputAccessoryView = secondView;
    
    [self.containerView addSubview:account];
}

#pragma mark - 創建一個密碼輸入框
-(void)createOnePasswordView{
    UITextField * password = [[UITextField alloc] initWithFrame:CGRectMake(40, 140, 200, 40)];
    self.password = password;
    self.password.delegate = self;
    password.backgroundColor = [UIColor lightGrayColor];
    password.placeholder = @"請輸入密碼";
    password.returnKeyType = UIReturnKeyNext;
    [self.containerView addSubview:password];
}

#pragma mark - 創建一個提交按鈕
-(void)createOneButton{
    UIButton * commit = [UIButton buttonWithType:UIButtonTypeCustom];
    commit.frame = CGRectMake(90, self.containerView.frame.size.height-100, 100, 40);
    self.commitButton = commit;
    [commit setTitle:@"提交" forState:UIControlStateNormal];
    commit.backgroundColor = [UIColor redColor];
    [self.containerView addSubview:commit];
}


#pragma mark - 註冊鍵盤通知
-(void)registerKeyboardNotification{

    //1、鍵盤將要顯示
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    
    //2、鍵盤顯示完成
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
    
    //3、鍵盤將要隱藏
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
    
    //4、鍵盤隱藏完成
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
    
    //5、鍵盤的frame將要變化的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil];
    
    //6、鍵盤的frame變化完成的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidChangeFrame:) name:UIKeyboardDidChangeFrameNotification object:nil];
    
}


-(void)keyboardWillShow:(NSNotification *)notification{
    //1、鍵盤將要彈出時調用此方法
    NSDictionary * userInfo = notification.userInfo;
//    NSLog(@"willShowUserInfo = %@",userInfo);
    //通知中各個參數說明
    /*
     UIKeyboardAnimationCurveUserInfoKey = 7;                               //動畫樣式
     UIKeyboardAnimationDurationUserInfoKey = "0.25";                       //動畫時間
     UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";          //鍵盤的bounds
     UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 796}";            //鍵盤變化開始時的center
     UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 538}";              //鍵盤變化結束時的center
     UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";    //鍵盤變化開始時的frame
     UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";      //鍵盤變化結束時的frame
     UIKeyboardIsLocalUserInfoKey = 1;                                      //ipad多任務同時運行,所有運行可見的app都會收到鍵盤通知,調出鍵盤的app返回的是1,其它app返回的是0

     */
    
    //解決鍵盤彈出覆蓋其它視圖的問題
    //鍵盤高度
    CGRect keyBoardFrame = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    
    CGFloat keyBoardY              = keyBoardFrame.origin.y;                       //鍵盤y座標

    //計算平移距離translationY 這裏一定要跟container的原始位置尺寸進行比較來計算 否則在兩個textFieldView之間進行切換時可能出現問題
    //大於0 證明有間隙
    //等於0 證明剛剛好
    //小於0 證明有覆蓋
    CGFloat translationY           = keyBoardY - (self.originalY + self.containerViewHeight);
    NSLog(@"translatinY = %lf",translationY);
    
#if 0 
    //只在被覆蓋的情況下才進行平移操作
    if (translationY < 0) {
        self.containerView.transform = CGAffineTransformMakeTranslation(0, translationY);
    }
    else{
        //else這部分代碼是不可少的 舉個例子:
        //1、第一次鍵盤彈出view被遮擋,view就會根據translationY進行平移
        //2、第二次鍵盤彈出時view沒被遮擋,view就需要回到原始位置,而不是待在平移後的位置
        //這種情況會出現在 在兩個或多個textFieldView之間切換時
        self.containerView.transform = CGAffineTransformIdentity;
    }
    
#elif 0
    //根據鍵盤的高度進行平移
    if (translationY < 0) {
        //鍵盤彈出被覆蓋 上移
        self.containerView.transform = CGAffineTransformMakeTranslation(0, translationY);
    }
    else if(translationY == 0){
        //剛剛好 就復原到原來位置  同上這部分是不可少的
        #if 0
        self.containerView.transform = CGAffineTransformMakeTranslation(0, 0);
        #else
        self.containerView.transform = CGAffineTransformIdentity;
        #endif
    }
    else{
        //與鍵盤有間隔 下移
        self.containerView.transform = CGAffineTransformMakeTranslation(0, translationY);
    }
    
#elif 0
    //其實上邊的代碼完全可以這麼寫就OK  這裏的關鍵是記錄下containerView最原始的位置信息
    self.containerView.transform = CGAffineTransformMakeTranslation(0, translationY);
    
#elif 1
    //通過這種方法也可以達到緊貼鍵盤的目的  而不用記錄原始位置信息
    CGFloat changeY   = self.containerView.frame.origin.y;          //view的實時Y座標
    CGFloat conHeight = self.containerView.frame.size.height;       //view的高度
    CGFloat keyY      = keyBoardFrame.origin.y;                     //鍵盤Y座標
    CGFloat changeTranslationY = keyY- (changeY + conHeight);
    self.containerView.transform = CGAffineTransformTranslate(self.containerView.transform , 0,changeTranslationY);
#endif
    
    
   /*********************************************************************************************************\
     *  PS:重要說明
     *  當在多個textField 之間切換時
     *  點擊第一個textField鍵盤彈出,此時再去點另外一個textFieldView,鍵盤是不會隱藏後再彈出的,而是一直保持彈出狀態。
     *  這個過程中textField的通知方法調用也不會來到keyboardWillHide方法,但會來到keyboardWillShow方法
     *
     *
   \*********************************************************************************************************/

    

}

-(void)keyboardDidShow:(NSNotification *)notification{
    //2、鍵盤彈出完成時調用此方法
    NSDictionary * userInfo = notification.userInfo;
//    NSLog(@"didShowUserInfo = %@",userInfo);
    /*
     
     UIKeyboardAnimationCurveUserInfoKey = 7;
     UIKeyboardAnimationDurationUserInfoKey = "0.25";
     UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";
     UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 796}";
     UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 538}";
     UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";
     UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";
     UIKeyboardIsLocalUserInfoKey = 1;
     
     */
   
}


-(void)keyboardWillHide:(NSNotification *)notification{
    //3、鍵盤將要隱藏式調用此方法
    NSDictionary * userInfo = notification.userInfo;
//    NSLog(@"willHideUserInfo = %@",userInfo);
    /*
     UIKeyboardAnimationCurveUserInfoKey = 7;
     UIKeyboardAnimationDurationUserInfoKey = "0.25";
     UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";
     UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 538}";
     UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 796}";
     UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";
     UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";
     UIKeyboardIsLocalUserInfoKey = 1;
     */
    
    self.containerView.transform   = CGAffineTransformIdentity;
}

-(void)keyboardDidHide:(NSNotification *)notification{
    //4、鍵盤隱藏完成時調用此方法
    NSDictionary * userInfo = notification.userInfo;
//    NSLog(@"didHideUserInfo = %@",userInfo);
    
    /*
     
     UIKeyboardAnimationCurveUserInfoKey = 7;
     UIKeyboardAnimationDurationUserInfoKey = "0.25";
     UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";
     UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 538}";
     UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 796}";
     UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";
     UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";
     UIKeyboardIsLocalUserInfoKey = 1;
     
     */
}

-(void)keyboardWillChangeFrame:(NSNotification *)notification{
    //5、只要鍵盤的frame發生變化就會來到此方法
   
   
}

-(void)keyboardDidChangeFrame:(NSNotification *)notification{
    //6、鍵盤的frame變化完成就會來都此方法
   
}

/*********************************************************************************************************\
 *  PS:重要說明
 *  鍵盤從彈出到隱藏的執行順序爲:
 *  5-1-6-2-5-3-6-4
 *
 *
 *
 \**********************************************************************************************************/

#pragma mark - UITextFieldDelegate
//1、是否允許編輯  yes爲允許 no爲否
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
    NSLog(@"是否可以開始編輯");
    return YES;
}

//2、已經開始編輯  開始編輯的時候會調用一次
- (void)textFieldDidBeginEditing:(UITextField *)textField{
    NSLog(@"已經開始編輯");
    
    
}


//3、是否允許改變內容
//yes當輸入時輸入框內容隨輸入改變 no不會改變
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
    //range.location返回的是輸入或刪除的字符所在的index
    //range.length 一個一個輸入時返回的總是0 一個一個刪除時返回的總是1 用來判斷是刪除還是輸入?
    //當剪切輸入框的內容時range.length 是剪切走的字符個數
    NSLog(@"range.location = %lu ,range.length = %lu",range.location,(unsigned long)range.length);
    //輸入或刪除的字符
    NSLog(@"string = %@",string);
    return YES;
}


//4、是否能結束編輯  yes爲允許 no爲否
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{
    NSLog(@"是否允許結束編輯");
    return YES;
}

//5、已經結束編輯
- (void)textFieldDidEndEditing:(UITextField *)textField{
    NSLog(@"已經結束編輯");
   
}

/**
 *  PS
 當只有一個textfield時,從點擊-編輯-離開的執行順序爲1、2、3、4、5
 如果是在兩個textfield之間切換,代理執行的順序是:
 點擊第一個testField:1、2、3、 編輯完成
 再點擊第二個testField:1、4、5、2、3、4、5
 *
 */

//6、是否允許清除 比如點擊刪除按鈕 或者設置了自動清除 就會來到此方法
//yes就會清除輸入框的內容,no不會清除
- (BOOL)textFieldShouldClear:(UITextField *)textField{
    
    return YES;
}

//7、點擊鍵盤右下角鍵來到此方法
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
    //取消第一響應者 收起鍵盤
    [textField resignFirstResponder];
    //疑問2:這裏返回yes跟no有什麼區別
    return YES;
}

//觸摸屏幕時調用
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
#if 1
    //註銷第一響應者 鍵盤會隱藏
    [self.account resignFirstResponder];
    [self.password resignFirstResponder];
#else
    //結束編輯鍵盤會隱藏
    [self.view endEditing:YES];
#endif
}

//最後不要忘記移除監聽者
-(void)dealloc{
#if 0
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillShowNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardDidShowNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillHideNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardDidHideNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardWillChangeFrameNotification
                                                  object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                                    name:UIKeyboardDidChangeFrameNotification
                                                  object:nil];
#else
    [[NSNotificationCenter defaultCenter] removeObserver:self];
#endif
}

@end


參考文章:

1、ios 監聽系統鍵盤的出現和消失-布布扣-bubuko.com

2、IOS中多個UITextField的鍵盤處理



發佈了126 篇原創文章 · 獲贊 8 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章