通过keyboardFrameWillChange显示键盘会导致表格数据滚出视图

时间:2015-05-08 21:48:45

标签: ios objective-c uitableview uiscrollview keyboard

已经挣扎了大约3天才能实现可滚动键盘的工作。这就是我所拥有的:

具有以下层次结构的UIViewController:

enter image description here

上图显示我有一个消息传递样式UITableView +“dockable”UIView,其中包含一个嵌入在View-> ScrollView-> ContentView中的textview和发送按钮。

在viewWillAppear中:

[[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中只有几个项目,我的代码会滚动视图的顶部,所以我再也见不到了。

我已经尝试调整tableview的大小,因为我相信正在发生的事情是scrollview正在滚动整个大小的tableview,而不是调整tableview的大小。我有一种强烈的感觉,我的观点很困惑,但我努力解决这个问题是徒劳的。

仅供参考,没有自动布局问题,所有内容都附加到正确的视图等(即UIView停靠在tableview下方和父卷轴视图的底部。

我该如何解决这个问题?

2 个答案:

答案 0 :(得分:1)

一些可能有用的建议:

不要同时更改framecontentInset;改变一个应该足够和容易管理。我建议只更改contentInset

UIKeyboardWillChangeFrameNotificationUIKeyboardDidChangeFrameNotification中的一个应告诉您所需的一切;你可以用一种方法处理键盘。当键盘隐藏时,框架将离屏。

当您撤消对contentInset的更改时,请将此属性恢复为您找到它的方式。 UIViewControllerautomatically adjust scroll view insets以避开状态栏,导航栏和工具栏或标签栏。这可能是您第一个问题的原因。

我知道图书馆是垃圾,但您可能想查看我的DHAvoidKeyboardBehaviour。至少它只有34行垃圾。

另外:您正在注册UIKeyboardWillChangeFrameNotification,但您的方法称为keyboardFrameDidChange:。关于 之间区别的草率会在某一天咬你。

答案 1 :(得分:0)

对于任何有兴趣的人,我都解决了自己的问题。

在keyboardFrameDidChange中,我将整个tableview向上移动以容纳键盘,这导致行显示在屏幕外。我缺少的是更改contentInsets以“调整大小”tableview以填充屏幕上的剩余空间。

对于键盘高度和为工具栏调整的底部,插入内容变得最高。 toolBar是固定在tableview下方底部的视图。

在viewWillAppear中:

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

在viewWillDisappear中:

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

感谢道格拉斯·希尔指出我的方向。