【问题标题】:How do I get scrollToRow to work within a UITableView on keyboard events?如何让 scrollToRow 在键盘事件的 UITableView 中工作?
【发布时间】:2021-01-18 14:46:24
【问题描述】:

我的视图控制器中有一个 tableView,它使 tableView 根据键盘是在屏幕上还是在屏幕外而缩小和扩展。当 tableView 缩小时,我希望它滚动到最后一行,但我无法让它工作。

目前,我有以下内容:

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

我也尝试将它放在主线程中。这让它在键盘第一次上升时工作。代码如下:

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

更新:

在字段中输入字母后以下工作(我希望它在键盘出现时正常工作)

注意:这是 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
}

【问题讨论】:

  • 奇怪的是,插图对我不起作用(表格视图保持相同的高度)
  • 你不应该改变表格视图的高度。而不是设置bottomConstraint.constant,只需设置插图。这将向上滚动所有内容,因此键盘不会覆盖它。
  • @green Checkout 我的解决方案适用于你。
  • 你的问题解决了吗?

标签: ios swift xcode uitableview


【解决方案1】:

斯威夫特 5

我已经根据您的逻辑测试了以下代码,因此您只需添加几行即可使其工作。

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

结果

我的代码的输出将是这样的:

【讨论】:

  • 感谢您的帮助,由于某种原因,它仍然表现得有些奇怪。我收到错误消息“来自调试器的消息:由于信号 9 而终止”
  • 它没有问题。粘贴你的代码,我会测试它
  • 抱歉耽搁了,如果有错误我会再试一次并粘贴我的代码
  • 差不多了:) 它看起来好多了。现在唯一的问题是我输入一个字母后它会滚动吗?所以我会输入一个字母,然后它会滚动(而不是在键盘启动时从头开始滚动)@Essam
  • 我还在最初的问题@Essam 下添加了代码
【解决方案2】:

更新约束后,您必须通过调用 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)
        }
    }

【讨论】:

  • 感谢您的帮助,我试过了,效果不错。唯一的挑战是 tableView 隐藏在键盘后面,直到使用键盘。所以(1)键盘出现,一些东西被隐藏(2)一个字母被输入,一切都向上滚动。有没有办法让它从头开始滚动,而不是在输入字母后滚动?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 2021-07-17
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多