当键盘出现在iOS 11上时,UITableView会将键盘高度添加到内容大小

问题描述 投票:4回答:3

我正在进行一项应该适用于iOS 11和12的聊天。在iOS 12上,一切都按预期工作。但是,在iOS 11上,我遇到键盘出现时表视图内容大小增加(无单元格)的问题。额外高度的数量与键盘高度相匹配。

演示

这是一个左侧是iOS 11,右侧是iOS 12的演示。在iOS 12上一切正常。当键盘出现时,请注意iOS 11上表格视图的底部。

Table view content size iOS 11 Table view content size iOS 12

查看/查看控制器层次结构设置

- =查看控制器 + =查看

- UINavigationViewController
    - UIViewController // Controlling contentInsets, contentOffset of the tableView
        + UIView
        - UITableViewController
            + UITableView
        - UIViewController // Controlling the text input bar at the bottom
            + ... // Other views
            + UITextView

布局约束

表视图的锚点等于其superview的锚点。所以全屏,忽略安全区域。因此,当键盘出现时,框架不会改变,但底部内容会插入。

更多细节

我设置了tableView.contentInsetAdjustmentBehavior = .never

这是我在键盘出现时计算表视图的插入和偏移的方法。这很复杂,因为有几种情况应该有不同的行为。当键盘消失时,以及文本输入的高度发生变化时,会出现类似的复杂计算。我总是想根据视图框架的变化向上或向下滚动表格视图。

@objc func handleKeyboardWillShowNotification(_ notification: NSNotification) {
    let frameEnd: CGRect = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as AnyObject).cgRectValue ?? .zero
    let keyboardHeight = frameEnd.height
    let contentHeight = tableView.contentSize.height
    let visibleTableViewHeight = tableView.frame.height - (tableView.contentInset.top + tableView.contentInset.bottom)
    let distanceToScroll = (keyboardHeight - view.safeAreaInsets.bottom)
    var y: CGFloat = 0
    if contentHeight > visibleTableViewHeight {
        y = tableView.contentOffset.y + distanceToScroll
    } else {
        let diff = visibleTableViewHeight - contentHeight
        let positionAtKeyboard = distanceToScroll - tableView.contentInset.top - diff
        y = positionAtKeyboard < tableView.contentInset.top ? -tableView.contentInset.top : positionAtKeyboard
    }
    let contentOffset = CGPoint(x: 0, y: y)
    tableView.contentInset.bottom = keyboardHeight + inputBar.frame.height
    tableView.scrollIndicatorInsets = tableView.contentInset
    tableView.setContentOffset(contentOffset, animated: false)
}

我也尝试过不同的屏幕尺寸,它总是增加一个与键盘高度完全匹配的contentSize

ios swift uitableview uiscrollview ios11
3个回答
0
投票

首先,您不必进行不必要的计算只需计算键盘高度,然后将键盘向上移动即可。

Swift版本:

@objc func keyboardWillShow(notification: NSNotification) {
    if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: keyboardSize.height + 10, right: 0)
        UIView.animate(withDuration: 0.25) {
            self.tableView.layoutIfNeeded()
            self.view.layoutIfNeeded()
        }
    }
}

@objc func keyboardWillHide(notification: NSNotification) {

    self.tableView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
    UIView.animate(withDuration: 0.5) {
        self.tableView.layoutIfNeeded()
        self.view.layoutIfNeeded()
    }
}

Objective-C版本:

- (void)keyboardWillShow:(NSNotification *)notification
{
    NSDictionary *keyInfo = [notification userInfo];
    CGRect keyboardFrame = [[keyInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];

    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardFrame.size.height + 10, 0);

    [UIView animateWithDuration:0.2 animations:^{
        [self.tableView layoutIfNeeded];
        [self.view layoutIfNeeded];
    } completion:nil];
}

- (void) keyboardWillHide:  (NSNotification *) notification
{
    self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
    [UIView animateWithDuration:0.2 animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];
}

如果您发现任何困难,请告诉我。这对我很有用


0
投票

您可以使用以下代码进行键盘隐藏和显示。

//显示键盘

@objc func keyboardWillAppear(_ notification: NSNotification) {
    if let newFrame = (notification.userInfo?[ UIResponder.keyboardFrameEndUserInfoKey ] as? NSValue)?.cgRectValue {
        if self.tableView.contentInset.bottom == 0 {
            let insets: UIEdgeInsets = UIEdgeInsets( top: 0, left: 0, bottom: newFrame.height, right: 0 )
            self.tableView.contentInset = insets
            self.tableView.scrollIndicatorInsets = insets
            UIView.animate(withDuration: 0.1) {
                self.view.layoutIfNeeded()
            }
        }
    }
}

//隐藏键盘

@objc func keyboardWillDisappear(_ notification: NSNotification) {
    if self.tableView.contentInset.bottom != 0 {
        self.tableView.contentInset = UIEdgeInsets( top: 0, left: 0, bottom: 0, right: 0 )
        self.tableView.scrollIndicatorInsets = UIEdgeInsets( top: 0, left: 0, bottom: 0, right: 0 )
        UIView.animate(withDuration: 0.1) {
            self.view.layoutIfNeeded()
        }
    }
}

这对我有用。


0
投票

解决方法

这不是专门回答原始问题,但可能是那些没有半透明键盘和输入视图的人的解决方案。

我可以通过更改约束而不设置底部插入来解决此问题。最初,表视图的底部约束设置在超级视图的底部(基本上是屏幕的底部)。所以当键盘出现时,我没有改变表格视图的框架,而是底部插入。这显然不能正常工作。

现在我将表视图的底部约束设置为输入视图(黑色条)的顶部,将底部插入设置为零。由于输入视图在键盘出现时向上移动,因此它会更改表格视图的框架,并且底部插入保持为零。我仍然设置内容偏移,因为我需要在不同情况下的特定行为,但就是这样。

这只适用于我的情况,因为我既没有半透明的输入条也没有键盘,也不需要在它后面显示模糊的内容。

© www.soinside.com 2019 - 2024. All rights reserved.