iOS實(shí)現(xiàn)輸入框跟隨鍵盤自動(dòng)上移的實(shí)例代碼
場景還原
有些時(shí)候在包含輸入框的頁面中,點(diǎn)擊輸入框輸入會(huì)因鍵盤彈起而遮擋住一部分輸入框,影響用戶體驗(yàn)。iOS在默認(rèn)情況下并不會(huì)處理這種問題,不過我們可以自己實(shí)現(xiàn)鍵盤彈起輸入框自動(dòng)上移的效果。
實(shí)現(xiàn)思路
觀察鍵盤的彈起與收回,當(dāng)彈起的鍵盤會(huì)遮擋住輸入框時(shí),將輸入框跟隨鍵盤一并上移合適的距離,當(dāng)鍵盤收回時(shí),輸入框回到原始狀態(tài)。
具體方案
1. 注冊兩個(gè)觀察者,觀察鍵盤的彈起與收回
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
2. 在上面的keyboardWillShow和keyboardWillHide方法中分別實(shí)現(xiàn)輸入框的上移和還原
上移
當(dāng)彈起的鍵盤遮住了頁面上的輸入框時(shí),我們應(yīng)該將輸入框移至鍵盤之上,而鍵盤沒有遮到輸入框時(shí),并不需要操作。因此在ios的坐標(biāo)系下,我們可以分別獲取鍵盤彈起后上端的Y坐標(biāo)和輸入框下端的Y坐標(biāo),通過做差可以判斷出鍵盤是否遮住了輸入框。上移我們可以采用view的transform屬性進(jìn)行平移變換,而不是直接去操作view的frame,這樣做的好處是當(dāng)我們要還原view的狀態(tài)時(shí)可以直接將transform重置為0,而不需要再關(guān)心計(jì)算下移時(shí)的距離。
還原(下移至原始狀態(tài))
根據(jù)前面所說,我們只要在恰當(dāng)?shù)臅r(shí)機(jī)操作view的transform屬性就可以實(shí)現(xiàn)了。
- (void)keyboardWillShow:(NSNotification *)notification { //獲取處于焦點(diǎn)中的view NSArray *textFields = @[phoneNemberText, verifyCodeText]; UIView *focusView = nil; for (UITextField *view in textFields) { if ([view isFirstResponder]) { focusView = view; break; } } if (focusView) { //獲取鍵盤彈出的時(shí)間 double duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; //獲取鍵盤上端Y坐標(biāo) CGFloat keyboardY = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y; //獲取輸入框下端相對于window的Y坐標(biāo) CGRect rect = [focusView convertRect:focusView.bounds toView:[[[UIApplication sharedApplication] delegate] window]]; CGPoint tmp = rect.origin; CGFloat inputBoxY = tmp.y + focusView.frame.size.height; //計(jì)算二者差值 CGFloat ty = keyboardY - inputBoxY; NSLog(@"position keyboard: %f, inputbox: %f, ty: %f", keyboardY, inputBoxY, ty); //差值小于0,做平移變換 [UIView animateWithDuration:duration animations:^{ if (ty < 0) { self.view.transform = CGAffineTransformMakeTranslation(0, ty); } }]; } } - (void)keyboardWillHide:(NSNotification *)notification { //獲取鍵盤彈出的時(shí)間 double duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]; //還原 [UIView animateWithDuration:duration animations:^{ self.view.transform = CGAffineTransformMakeTranslation(0, 0); }]; }
看上去這樣已經(jīng)完美實(shí)現(xiàn)了輸入框隨鍵盤自動(dòng)上移,我們也可以喝杯茶稍微休息一下了。沒錯(cuò),在iOS 8及之后的系統(tǒng)中,確實(shí)可以正常的工作,然而如果你的應(yīng)用需要適配iOS 7并且要支持橫屏,那么上面的方式在iOS7上,并不能按照我們的期望正確移動(dòng)。
原因:在ios7上,鍵盤的frame,系統(tǒng)是按照豎屏狀態(tài)下window坐標(biāo)系來計(jì)算的,并不考慮旋轉(zhuǎn)的因素,因此在橫屏下得到的鍵盤frame是錯(cuò)誤的。受此影響的還有橫屏?xí)r獲取屏幕寬高[UIScreen mainScreen].bounds,也會(huì)有這樣的問題。這種情況我們不僅無法正確得到鍵盤的frame,而且輸入框相對于window的坐標(biāo)計(jì)算結(jié)果也是錯(cuò)誤的。
因此在ios7上,鍵盤上端的Y坐標(biāo)以及輸入框下端相對于window的Y坐標(biāo)需要單獨(dú)處理。鍵盤上端的Y坐標(biāo)可以通過屏幕高度減鍵盤高度得到。我們通過下面的方法獲取鍵盤上端的Y坐標(biāo)。
- (CGFloat)getKeyboardY:(NSDictionary *)userInfo { CGFloat screenHeight; CGFloat keyboardY = 0; CGFloat keyboardHeight = 0; UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if (( [[[UIDevice currentDevice] systemVersion] floatValue]<8) && UIInterfaceOrientationIsLandscape(orientation)) { screenHeight = [[UIScreen mainScreen] bounds].size.width; keyboardHeight = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.width; keyboardY = screenHeight - keyboardHeight; } else if (( [[[UIDevice currentDevice] systemVersion] floatValue]<8) && UIInterfaceOrientationIsPortrait(orientation)) { screenHeight = [[UIScreen mainScreen] bounds].size.height; keyboardHeight = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].size.height; keyboardY = screenHeight - keyboardHeight; } else { keyboardY = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue].origin.y; } return keyboardY; }
輸入框下端相對于window的坐標(biāo)如何計(jì)算呢?我們首先獲得的其實(shí)是基于豎屏狀態(tài)下坐標(biāo)系中的Y值,而我們期望的是橫屏下得到橫屏狀態(tài)下坐標(biāo)系中的Y值,根據(jù)兩個(gè)坐標(biāo)系的關(guān)系,可以將第一次轉(zhuǎn)換得到的坐標(biāo)再做一次轉(zhuǎn)換,計(jì)算得出橫屏坐標(biāo)系下的Y坐標(biāo)值。我們通過下面的方法獲取輸入框下端的Y坐標(biāo)。
- (CGPoint)getViewOriginPointToWindow:(UIView *)view { CGPoint origin; if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8) { CGPoint focusViewPoint = [view convertPoint:CGPointZero toView:nil]; UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if (orientation == UIInterfaceOrientationLandscapeLeft) { origin.y = focusViewPoint.x; origin.x = [[[UIApplication sharedApplication] delegate] window].bounds.size.height - focusViewPoint.y; } else if (orientation == UIInterfaceOrientationLandscapeRight) { origin.y = [[[UIApplication sharedApplication] delegate] window].bounds.size.width - focusViewPoint.x; origin.x = focusViewPoint.y; } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { origin.y = [[[UIApplication sharedApplication] delegate] window].bounds.size.height - focusViewPoint.y; origin.x = [[[UIApplication sharedApplication] delegate] window].bounds.size.width - focusViewPoint.x; } else { origin = focusViewPoint; } } else { CGRect rect = [view convertRect:view.bounds toView:[[[UIApplication sharedApplication] delegate] window]]; origin = rect.origin; } return origin; }
因此我們將之前獲取兩個(gè)Y坐標(biāo)的代碼改用下面的方式:
//獲取鍵盤上端Y坐標(biāo) CGFloat keyboardY = [self getKeyboardY:notification.userInfo]; //獲取輸入框下端相對于window的Y坐標(biāo) CGPoint tmp = [self getViewOriginPointToWindow:focusView]; CGFloat inputBoxY = tmp.y + focusView.frame.size.height;
這樣就完美實(shí)現(xiàn)了輸入框隨鍵盤自動(dòng)上移的效果。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Objective-C編程中語句和變量的一些編寫規(guī)范建議
這篇文章主要介紹了Objective-C編程中語句和變量的一些編寫規(guī)范建議,包括三目運(yùn)算符和錯(cuò)誤處理等方面,以及對變量命名的書寫建議,需要的朋友可以參考下2016-04-04iOS 使用Moya網(wǎng)絡(luò)請求的實(shí)現(xiàn)方法
這篇文章主要介紹了iOS 使用Moya網(wǎng)絡(luò)請求的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-07-07iOS開發(fā)-自定義相機(jī)實(shí)例(仿微信)
這篇文章主要介紹了iOS開發(fā)-自定義相機(jī)實(shí)例(仿微信),實(shí)例分析了ios 自定義相機(jī)的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2017-03-03禁止iPhone Safari video標(biāo)簽視頻自動(dòng)全屏的辦法
本篇文章給大家分析有沒有辦法禁止iPhone Safari video標(biāo)簽視頻自動(dòng)全屏,以下給出好多種情況分享,感興趣的朋友可以參考下2015-09-09iOS開發(fā)技巧之狀態(tài)欄字體顏色的設(shè)置方法
有時(shí)候我們需要根據(jù)不同的背景修改狀態(tài)欄字體的顏色,下面這篇文章主要給大家介紹了關(guān)于iOS開發(fā)技巧之狀態(tài)欄字體顏色的設(shè)置方法,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來一起看看吧2018-08-08