解决UITextField在键盘弹出时的上移问题

解决UITextField在键盘弹出时的上移问题

技术背景

在iOS开发中,当用户点击UITextField进行输入时,键盘会弹出,可能会遮挡住UITextField,影响用户输入体验。因此,需要实现当键盘弹出时,UITextField能够自动上移到可见区域。

实现步骤

不使用UIScrollView的方法

若内容能适配iPhone屏幕,无需使用UIScrollView,可通过移动视图来避免UITextField被键盘遮挡。

  1. 注册键盘通知:在viewWillAppear方法中注册UIKeyboardWillShowNotificationUIKeyboardWillHideNotification通知。
  2. 实现键盘显示和隐藏的处理方法:在keyboardWillShowkeyboardWillHide方法中,根据键盘的显示和隐藏来移动视图。
  3. 处理文本字段开始编辑的事件:在textFieldDidBeginEditing方法中,根据需要移动视图。

使用UIScrollView的方法

若内容无法适配iPhone屏幕,则需要使用UIScrollView

  1. 确保contentSize大于UIScrollView的框架大小:这样UIScrollView才能滚动。
  2. 注册键盘通知:在viewDidLoad方法中注册UIKeyboardWillShowNotificationUIKeyboardWillHideNotification通知。
  3. 调整UIScrollView的大小和内容偏移量:在keyboardWillShowkeyboardWillHide方法中,根据键盘的显示和隐藏来调整UIScrollView的大小和内容偏移量。

使用第三方库IQKeyboardManager

IQKeyboardManager是一个方便的第三方库,可自动处理键盘和UITextField的问题。

  1. 添加依赖:在Podfile中添加pod 'IQKeyboardManager',然后执行pod install
  2. 启用库:在AppDelegate中启用IQKeyboardManager

核心代码

不使用UIScrollView的Objective - C代码示例

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];
}

使用UIScrollView的Objective - C代码示例

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重复调整大小,可使用一个标志位来避免。
  • 视图未恢复原位:在文本字段结束编辑时,确保视图能恢复到原来的位置。

解决UITextField在键盘弹出时的上移问题
https://119291.xyz/posts/solve-uitextfield-move-up-problem-when-keyboard-pops-up/
作者
ww
发布于
2025年5月26日
许可协议