簡體   English   中英

當鍵盤出現在iOS11上時,UITableView會將鍵盤高度添加到contentSize

[英]UITableView adds height of keyboard to contentSize when the keyboard appears on iOS11

我正在進行一項應該適用於iOS 11和12的聊天。在iOS 12上,一切都按預期工作。 但是,在iOS 11上,我遇到鍵盤出現時表視圖內容大小增加(無單元格)的問題。 額外高度的數量與鍵盤高度相匹配。

演示

這是一個左側是iOS 11,右側是iOS 12的演示。 在iOS 12上一切正常。 當鍵盤出現時,請注意iOS 11上表格視圖的底部。

表視圖內容大小iOS 11 表視圖內容大小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添加一個與鍵盤高度完全匹配的數量。

首先,您不必進行不必要的計算只需計算鍵盤高度,然后將鍵盤向上移動即可。

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()
    }
}

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

如果您發現任何困難,請告訴我。 這對我很有用

您可以使用以下代碼進行鍵盤隱藏和顯示。

//顯示鍵盤

@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()
        }
    }
}

這對我有用。

解決方法

這不是專門回答原始問題,但可能是那些沒有半透明鍵盤和輸入視圖的人的解決方案。

我可以通過更改約束而不設置底部插入來解決此問題。 最初,表視圖的底部約束設置在超級視圖的底部(基本上是屏幕的底部)。 所以當鍵盤出現時,我沒有改變表格視圖的框架,而是底部插入。 這顯然不能正常工作。

現在我將表視圖的底部約束設置為輸入視圖(黑色條)的頂部,將底部插入設置為零。 由於輸入視圖在鍵盤出現時向上移動,因此它會更改表格視圖的框架,並且底部插入保持為零。 我仍然設置內容偏移,因為我需要在不同情況下的特定行為,但就是這樣。

這只適用於我的情況,因為我既沒有半透明的輸入條也沒有鍵盤,也不需要在它后面顯示模糊的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM