简体   繁体   English

如何让 scrollToRow 在键盘事件的 UITableView 中工作?

[英]How do I get scrollToRow to work within a UITableView on keyboard events?

I have a tableView in my view controller and I have it such that the tableView shrinks and expands depending on whether the keyboard is on the screen or off the screen.我的视图控制器中有一个 tableView 并且我有它,这样 tableView 会根据键盘是在屏幕上还是屏幕外来收缩和扩展。 When the tableView shrinks, I want it to scroll to the bottom row but I can't get this to work.当 tableView 缩小时,我希望它滚动到底行,但我无法让它工作。

Currently, I have the following:目前,我有以下几点:

@objc func keyboardAppears(notification: Notification) {
        if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
                bottomConstraint.constant = -1 * keyboardFrame.height
                view.loadViewIfNeeded()
                tableView.scrollToRow(at: IndexPath(row: 10, section: 0), at: .top, animated: true)
         }
}

I also tried putting it in the main thread.我也试过把它放在主线程中。 This got it to work the first time the keyboard went up only.这使它在第一次键盘上升时起作用。 The code looked as follows:代码如下所示:

@objc func keyboardAppears(notification: Notification) {
        if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
                bottomConstraint.constant = -1 * keyboardFrame.height
                view.loadViewIfNeeded()
                parentView.scrollUp()
         }
}

func scrollUp() {
        DispatchQueue.main.async {
            self.entrySpace.scrollToRow(at: IndexPath(row: self.data.count - 1, section: 0), at: .top, animated: true)
        }
}

UPDATE:更新:

The following works after a letter is typed in the field (I want it to work right when the keyboard comes up)在字段中输入一个字母后,以下工作(我希望它在键盘出现时正常工作)

NOTE: this is the UITableViewCell class because the cell is the last item in the UITableView注意:这是 UITableViewCell 类,因为单元格是 UITableView 中的最后一项

import UIKit

class EntryButtonCell: UITableViewCell {
    
    //the textView for new entries
    var entryCell = UITextView()
    
    //Reference to the parent table
    var parentTable = UITableView()

    //Reference to the parent view (the one that holds the table view)
    var parentView = ParentVC()

    var bottomConstraint = NSLayoutConstraint()
    
    //Initialization
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        //set this cell as the delegate for the entry textView
        entryCell.delegate = self
        
        //deactivate interaction with the cell so the user can interact with the textView
        contentView.isUserInteractionEnabled = false
        
        //set up the textView
        prepTextView()
        
        //set the notification for the keyboard events
        setKeyboardObservers()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    //deinitialization
    deinit {
        //remove the keyboard observers
        removeKeyboardObservers()
    }
    
    func prepTextView() {
        //just did the constraints here 
        //removing to save space
    }
    
    func scrollToBottom() {
        DispatchQueue.main.async { [weak self] in
            guard let data = self?.parentView.data else { return }
            let indexPath = IndexPath(row: data.count, section: 0)
            self?.parentTable.scrollToRow(at: indexPath, at: .bottom, animated: true)
        }
    }
    
    //set the keyboard notification
    private func setKeyboardObservers() {
        //add keyboardWillShowNotification
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardAppears(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        
        //add keyboardWillHideNotification
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardDisappears(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    //deactivate the keyboard notifications
    private func removeKeyboardObservers() {
       //deactivate keyboardWillShowNotification
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
        
        //deactivate keyboardWillHideNotification
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    //run when keyboard shows
    @objc func keyboardAppears(notification: Notification) {
        if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
            
                scrollToBottom()
                bottomConstraint.constant = -1 * keyboardFrame.height
                parentTable.layoutSubviews()
                parentView.loadViewIfNeeded()
        }
    }

    @objc func keyboardDisappears(notification: Notification) {
        tableBottomConstraint.constant = -100.0
        parentView.loadViewIfNeeded()
    }

    //Took out a few of the textView methods to save space
}

Swift 5斯威夫特 5

I have tested the following code based on your logic so that you just add a few lines to get it to work.我已经根据您的逻辑测试了以下代码,因此您只需添加几行即可使其工作。

// MARK: Keyboard Handling

@objc func keyboardWillShow(notification: Notification)
{
    if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect
    {
        tableView.reloadData()
        scrollToBottom()
        
        tableBottomConstraint.constant = -1 * (keyboardFrame.height + 100)
        loadViewIfNeeded()
    }
}

@objc func keyboardWillHide(notification: Notification)
{
    tableBottomConstraint.constant = -100.0
    loadViewIfNeeded()
}

func scrollToBottom()
{
    DispatchQueue.main.async { [weak self] in
        guard let data = self?.data else { return }
        let indexPath = IndexPath(row: data.count - 1, section: 0)
        self?.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
    }
}

Result结果

The output of my code will be something like this:我的代码的输出将是这样的:

在此处输入图片说明

在此处输入图片说明

After updating a constraint, you have to commit the update by calling the layoutSubview() and after that you can call the scrollToRow(at:at:animated) method.更新约束后,您必须通过调用 layoutSubview() 提交更新,然后您可以调用 scrollToRow(at:at:animated) 方法。

@objc func keyboardAppears(notification: Notification) {
        if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
            bottomConstraint.constant = -keyboardFrame.height
            view.layoutSubviews()
            self.entrySpace.scrollToRow(at: IndexPath(row: self.data.count - 1, section: 0), at: .top, animated: true)
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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