简体   繁体   中英

UITableView Scrolling/Inset Issue

I have a UITableView with multiple textfields. When I click on a textfield, I setContentOffset to bring the textfield to the top of the page, but I do not have enough inset to do so when the keyboard appears. So I added inset to the bottom of the view. This allows me to scroll all the way down but now when I select a field it scrolls down too far, further than the setContentOffset that I set. I've tried different content inset values, but none work. Is there a way to fix this content inset issue?

func adjustInsetForKeyboardShow(_ show: Bool, notification: Notification) {
        if !keyboardAdjusted || !show {
            guard let value = (notification as NSNotification).userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue else { return }
            let keyboardFrame = value.cgRectValue
            var adjustmentHeight = (keyboardFrame.height + 100) * (show ? 1 : -1)
            adjustmentHeight = (adjustmentHeight < 0.0) ? 0.0 : adjustmentHeight

            self.editPaymentTableView.contentInset.bottom = adjustmentHeight
            self.editPaymentTableView.scrollIndicatorInsets.bottom = adjustmentHeight
        }
        keyboardAdjusted = show
    }

I've found this on SO some time ago, but can't find the link to it anymore, here is the code that very neatly handles the keyboard and the insets of the tableview. Nice thing is it's for showing and hiding. No need to implement other keyboard notifications:

public func keyboardWillChangeFrame(notification: NSNotification) {
    guard
        let userInfo = notification.userInfo,
        let endFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue,
        let duration: TimeInterval = (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber)?.doubleValue,
        let animationCurveRawNSNumber = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber
        else {
            return
    }

    let animationCurveRaw = animationCurveRawNSNumber.uintValue
    let animationCurve: UIViewAnimationOptions = UIViewAnimationOptions(rawValue: animationCurveRaw)

    let offsetY: CGFloat
    if endFrame.origin.y >= UIScreen.main.bounds.size.height {
        offsetY = 0.0
    } else {
        offsetY = endFrame.size.height
    }

    let contentInsets = UIEdgeInsetsMake(0, 0, offsetY, 0)
    UIView.animate(withDuration: duration, delay: TimeInterval(0), options: animationCurve, animations: {
        self.tableView.contentInset = contentInsets
        self.tableView.scrollIndicatorInsets = contentInsets
    }, completion: nil)
}

In terms of your solution, you can replace these two lines:

var adjustmentHeight = (keyboardFrame.height + 100) * (show ? 1 : -1)
adjustmentHeight = (adjustmentHeight < 0.0) ? 0.0 : adjustmentHeight

with:

var adjustmentHeight = keyboardFrame.height * (show ? 1 : 0)

And to be sure that you're also setting top inset to 0 do:

let contentInsets = UIEdgeInsetsMake(0, 0, adjustmentHeight, 0)
self.editPaymentTableView.contentInset = contentInsets

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM