通过 keyboardFrameWillChange 显示键盘会导致 table 数据滚出视图
Showing keyboard via keyboardFrameWillChange causes table data to scroll out of view
努力了大约 3 天来实现可滚动键盘的工作。这是我拥有的:
具有以下层次结构的 UIViewController:
上图显示我有一个消息传递样式 UITableView + "dockable" 带有文本视图的 UIView 和嵌入在 View->ScrollView->ContentView 中的发送按钮。
在视图中会出现:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardFrameDidChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
并且实施了 keyboardFrameWillChange:
- (void)keyboardFrameWillChange:(NSNotification *)notification
{
CGRect endFrame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
UIViewAnimationOptions options = (curve << 16) | UIViewAnimationOptionBeginFromCurrentState;
CGRect newFrame = self.view.frame;
newFrame.origin.y = endFrame.origin.y - newFrame.size.height;
[UIView animateWithDuration:duration delay:0 options:options animations:^{
self.view.frame = newFrame;
} completion:nil];
}
这让我仅通过使用 keyboardFrameWillChange 就可以几乎完全正常地显示和隐藏键盘。这包括在故事板上设置键盘拖动消除。
不过我遇到了一个问题:整个视图(无论是什么视图)都在移动,所以如果表视图中只有几个项目,我的代码会将视图的顶部滚动到这样我就再也看不到它们了。
我已经尝试调整 tableview 的大小,因为我 相信 正在发生的是 scrollview 正在滚动完整大小的 tableview,而不是调整 tableview 的大小。我有一种强烈的感觉,我的观点被混淆了,但我为解决这个问题所做的努力是徒劳的。
仅供参考,没有自动布局问题,所有内容都附加到正确的视图等(即 UIView 停靠在表格视图下方和父滚动视图的底部。
我该如何解决?
一些可能有用的建议:
不要同时更改 frame
和 contentInset
;只改变一个应该就足够了,而且更容易管理。我建议只更改 contentInset
.
UIKeyboardWillChangeFrameNotification
或 UIKeyboardDidChangeFrameNotification
之一应该会告诉您所需的一切;您可以用一种方法处理键盘。当键盘隐藏时,框架将离开屏幕。
撤消对 contentInset
的更改后,将此 属性 恢复到您找到它的状态。 UIViewController
将automatically adjust scroll view insets 避开状态栏、导航栏和工具栏或标签栏。这可能是您第一个问题的原因。
我知道图书馆是垃圾,但你可能想看看我的 DHAvoidKeyboardBehaviour。至少只有34行垃圾
此外:您正在注册 UIKeyboardWillChangeFrameNotification
,但您的方法名为 keyboardFrameDidChange:
。草率区分 will 和 did 总有一天会咬你一口。
对于任何感兴趣的人,我解决了我自己的问题。
在 keyboardFrameDidChange 中,我将整个表格视图向上移动以适应键盘,这导致行出现在屏幕外。我缺少的是将 contentInsets 更改为 "resize" 表格视图以填充屏幕上剩余的 space。
插图顶部根据键盘高度调整,底部根据工具栏调整。 toolBar 是锚定在 tableview 下方底部的视图。
在视图中会出现:
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeShown:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardFrameWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
在视图中会消失:
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
keyboardWillBeShown 的实现:
NSLog(@"Keyboard will be shown");
CGRect keyboardFrame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(keyboardFrame.size.height, 0.0, toolBar.bounds.size.height, 0.0);
tableView.contentInset = contentInsets;
tableView.scrollIndicatorInsets = contentInsets;
keyboardWillBeHidden 的实现:
NSLog(@"Keyboard will be hidden");
tableView.contentInset = UIEdgeInsetsZero;
tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
keyboardFrameWillChange 的实现:
NSLog(@"Keyboard frame will change");
NSTimeInterval duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
UIViewAnimationOptions options = (curve << 16) | UIViewAnimationOptionBeginFromCurrentState;
CGRect keyboardFrame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect contentFrame = self.view.frame;
contentFrame.origin.y = keyboardFrame.origin.y - contentFrame.size.height;
[UIView animateWithDuration:duration delay:0 options:options animations:^{
self.view.frame = contentFrame;
} completion:nil];
感谢 Douglas Hill 为我指明了大致的方向。
努力了大约 3 天来实现可滚动键盘的工作。这是我拥有的:
具有以下层次结构的 UIViewController:
上图显示我有一个消息传递样式 UITableView + "dockable" 带有文本视图的 UIView 和嵌入在 View->ScrollView->ContentView 中的发送按钮。
在视图中会出现:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardFrameDidChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
并且实施了 keyboardFrameWillChange:
- (void)keyboardFrameWillChange:(NSNotification *)notification
{
CGRect endFrame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
UIViewAnimationOptions options = (curve << 16) | UIViewAnimationOptionBeginFromCurrentState;
CGRect newFrame = self.view.frame;
newFrame.origin.y = endFrame.origin.y - newFrame.size.height;
[UIView animateWithDuration:duration delay:0 options:options animations:^{
self.view.frame = newFrame;
} completion:nil];
}
这让我仅通过使用 keyboardFrameWillChange 就可以几乎完全正常地显示和隐藏键盘。这包括在故事板上设置键盘拖动消除。
不过我遇到了一个问题:整个视图(无论是什么视图)都在移动,所以如果表视图中只有几个项目,我的代码会将视图的顶部滚动到这样我就再也看不到它们了。
我已经尝试调整 tableview 的大小,因为我 相信 正在发生的是 scrollview 正在滚动完整大小的 tableview,而不是调整 tableview 的大小。我有一种强烈的感觉,我的观点被混淆了,但我为解决这个问题所做的努力是徒劳的。
仅供参考,没有自动布局问题,所有内容都附加到正确的视图等(即 UIView 停靠在表格视图下方和父滚动视图的底部。
我该如何解决?
一些可能有用的建议:
不要同时更改 frame
和 contentInset
;只改变一个应该就足够了,而且更容易管理。我建议只更改 contentInset
.
UIKeyboardWillChangeFrameNotification
或 UIKeyboardDidChangeFrameNotification
之一应该会告诉您所需的一切;您可以用一种方法处理键盘。当键盘隐藏时,框架将离开屏幕。
撤消对 contentInset
的更改后,将此 属性 恢复到您找到它的状态。 UIViewController
将automatically adjust scroll view insets 避开状态栏、导航栏和工具栏或标签栏。这可能是您第一个问题的原因。
我知道图书馆是垃圾,但你可能想看看我的 DHAvoidKeyboardBehaviour。至少只有34行垃圾
此外:您正在注册 UIKeyboardWillChangeFrameNotification
,但您的方法名为 keyboardFrameDidChange:
。草率区分 will 和 did 总有一天会咬你一口。
对于任何感兴趣的人,我解决了我自己的问题。
在 keyboardFrameDidChange 中,我将整个表格视图向上移动以适应键盘,这导致行出现在屏幕外。我缺少的是将 contentInsets 更改为 "resize" 表格视图以填充屏幕上剩余的 space。
插图顶部根据键盘高度调整,底部根据工具栏调整。 toolBar 是锚定在 tableview 下方底部的视图。
在视图中会出现:
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeShown:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillBeHidden:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardFrameWillChange:) name:UIKeyboardWillChangeFrameNotification object:nil];
在视图中会消失:
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self];
keyboardWillBeShown 的实现:
NSLog(@"Keyboard will be shown");
CGRect keyboardFrame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
UIEdgeInsets contentInsets = UIEdgeInsetsMake(keyboardFrame.size.height, 0.0, toolBar.bounds.size.height, 0.0);
tableView.contentInset = contentInsets;
tableView.scrollIndicatorInsets = contentInsets;
keyboardWillBeHidden 的实现:
NSLog(@"Keyboard will be hidden");
tableView.contentInset = UIEdgeInsetsZero;
tableView.scrollIndicatorInsets = UIEdgeInsetsZero;
keyboardFrameWillChange 的实现:
NSLog(@"Keyboard frame will change");
NSTimeInterval duration = [[notification.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
UIViewAnimationCurve curve = [[notification.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
UIViewAnimationOptions options = (curve << 16) | UIViewAnimationOptionBeginFromCurrentState;
CGRect keyboardFrame = [[notification.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect contentFrame = self.view.frame;
contentFrame.origin.y = keyboardFrame.origin.y - contentFrame.size.height;
[UIView animateWithDuration:duration delay:0 options:options animations:^{
self.view.frame = contentFrame;
} completion:nil];
感谢 Douglas Hill 为我指明了大致的方向。