解决UITextField在键盘弹出时的上移问题
技术背景
在iOS开发中,当用户点击UITextField
进行输入时,键盘会弹出,可能会遮挡住UITextField
,影响用户输入体验。因此,需要实现当键盘弹出时,UITextField
能够自动上移到可见区域。
实现步骤
若内容能适配iPhone屏幕,无需使用UIScrollView
,可通过移动视图来避免UITextField
被键盘遮挡。
- 注册键盘通知:在
viewWillAppear
方法中注册UIKeyboardWillShowNotification
和UIKeyboardWillHideNotification
通知。 - 实现键盘显示和隐藏的处理方法:在
keyboardWillShow
和keyboardWillHide
方法中,根据键盘的显示和隐藏来移动视图。 - 处理文本字段开始编辑的事件:在
textFieldDidBeginEditing
方法中,根据需要移动视图。
若内容无法适配iPhone屏幕,则需要使用UIScrollView
。
- 确保
contentSize
大于UIScrollView
的框架大小:这样UIScrollView
才能滚动。 - 注册键盘通知:在
viewDidLoad
方法中注册UIKeyboardWillShowNotification
和UIKeyboardWillHideNotification
通知。 - 调整
UIScrollView
的大小和内容偏移量:在keyboardWillShow
和keyboardWillHide
方法中,根据键盘的显示和隐藏来调整UIScrollView
的大小和内容偏移量。
使用第三方库IQKeyboardManager
IQKeyboardManager
是一个方便的第三方库,可自动处理键盘和UITextField
的问题。
- 添加依赖:在
Podfile
中添加pod 'IQKeyboardManager'
,然后执行pod install
。 - 启用库:在
AppDelegate
中启用IQKeyboardManager
。
核心代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| #define kOFFSET_FOR_KEYBOARD 80.0
-(void)keyboardWillShow { if (self.view.frame.origin.y >= 0) { [self setViewMovedUp:YES]; } else if (self.view.frame.origin.y < 0) { [self setViewMovedUp:NO]; } }
-(void)keyboardWillHide { if (self.view.frame.origin.y >= 0) { [self setViewMovedUp:YES]; } else if (self.view.frame.origin.y < 0) { [self setViewMovedUp:NO]; } }
-(void)textFieldDidBeginEditing:(UITextField *)sender { if ([sender isEqual:mailTf]) { if (self.view.frame.origin.y >= 0) { [self setViewMovedUp:YES]; } } }
-(void)setViewMovedUp:(BOOL)movedUp { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.3];
CGRect rect = self.view.frame; if (movedUp) { rect.origin.y -= kOFFSET_FOR_KEYBOARD; rect.size.height += kOFFSET_FOR_KEYBOARD; } else { rect.origin.y += kOFFSET_FOR_KEYBOARD; rect.size.height -= kOFFSET_FOR_KEYBOARD; } self.view.frame = rect; [UIView commitAnimations]; }
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide) name:UIKeyboardWillHideNotification object:nil]; }
- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| - (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:self.view.window]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:self.view.window]; keyboardIsShown = NO; CGSize scrollContentSize = CGSizeMake(320, 345); self.scrollView.contentSize = scrollContentSize; }
- (void)keyboardWillHide:(NSNotification *)n { NSDictionary* userInfo = [n userInfo]; CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size; CGRect viewFrame = self.scrollView.frame; viewFrame.size.height += (keyboardSize.height - kTabBarHeight); [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [self.scrollView setFrame:viewFrame]; [UIView commitAnimations]; keyboardIsShown = NO; }
- (void)keyboardWillShow:(NSNotification *)n { if (keyboardIsShown) { return; } NSDictionary* userInfo = [n userInfo]; CGSize keyboardSize = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
CGRect viewFrame = self.scrollView.frame; viewFrame.size.height -= (keyboardSize.height - kTabBarHeight); [UIView beginAnimations:nil context:NULL]; [UIView setAnimationBeginsFromCurrentState:YES]; [self.scrollView setFrame:viewFrame]; [UIView commitAnimations]; keyboardIsShown = YES; }
|
Swift代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| func animateTextField(textField: UITextField, up: Bool) { let movementDistance: CGFloat = -130 let movementDuration: Double = 0.3 var movement:CGFloat = 0 if up { movement = movementDistance } else { movement = -movementDistance } UIView.animate(withDuration: movementDuration, delay: 0, options: [.beginFromCurrentState]) { self.view.frame = self.view.frame.offsetBy(dx: 0, dy: movement) } }
func textFieldDidBeginEditing(_ textField: UITextField) { animateTextField(textField: textField, up: true) }
func textFieldDidEndEditing(_ textField: UITextField) { animateTextField(textField: textField, up: false) }
|
最佳实践
- 使用第三方库:如
IQKeyboardManager
,可大大减少代码量,提高开发效率。 - 考虑不同屏幕尺寸和设备方向:确保在各种情况下都能正常工作。
- 使用自动布局:结合自动布局可以更好地适应不同的屏幕尺寸和设备方向。
常见问题
- 滚动异常:若
UIScrollView
滚动异常,需确保contentSize
大于UIScrollView
的框架大小。 - 重复调整大小:当键盘已经显示时,再次收到键盘显示通知可能会导致
UIScrollView
重复调整大小,可使用一个标志位来避免。 - 视图未恢复原位:在文本字段结束编辑时,确保视图能恢复到原来的位置。