微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在用户可见之前将 UITableView 滚动到所需的行?

如何解决如何在用户可见之前将 UITableView 滚动到所需的行?

我想知道,是否可以将 UITableView 滚动到所需的行,甚至在用户可见之前,以便用户不知道此类滚动操作?

目前,这是我执行滚动到所需行的代码

class TheMetableViewController: UITableViewController {
    private var firstTime = true
 
    private func scrollRectToVisible() {
        let theme = WeNoteOptions.theme
        if let index = Theme.allCases.firstIndex(of: theme) {
            let indexPath = IndexPath(row: index,section: 0)
            let rect = tableView.rectForRow(at: indexPath)
            tableView.scrollRectToVisible(rect,animated: true)
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        if firstTime {
            firstTime.toggle()
            scrollRectToVisible()
        }
    }

请注意,在以下函数中放置 scrollRectToVisible 将不起作用。到目前为止,viewDidAppearscrollRectToVisible 唯一工作的地方。

  • viewDidLoad - scrollRectToVisible 在这里不起作用。
  • viewWillAppear - scrollRectToVisible 在这里不起作用。

这是目前的结果。

enter image description here

用户会注意到自动滚动操作。

我们希望用户不知道滚动操作。

是否有可能当用户第一次看到 UITableView 时,最后一行(绿色鳄梨)已经可见?

解决方法

如果您的单元格可能具有动态高度,您可能会发现这更可靠:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if firstTime {
        if tableView.numberOfRows(inSection: 0) != 0 {
            firstTime = false
            tableView.scrollToRow(at: IndexPath(row: tableView.numberOfRows(inSection: 0) - 1,section: 0),at: .bottom,animated: false)
        }
    }
}

使用以下示例进行测试...单元格将在标签中包含 2 到 6 行文本。注释/取消注释 viewDidLayoutSubviews() 中的不同方法:

class MyTableVC: UITableViewController {
    
    private var firstTime = true

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(MyCell.self,forCellReuseIdentifier: "myCell")
    }
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        if firstTime {
            if tableView.numberOfRows(inSection: 0) != 0 {
                firstTime = false
                
                // note the difference between this
                tableView.scrollToRow(at: IndexPath(row: tableView.numberOfRows(inSection: 0) - 1,animated: false)
                
                // and this
                //scrollRectToVisible()
            }
        }
    }
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    override func tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int {
        return 30
    }
    override func tableView(_ tableView: UITableView,cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let c = tableView.dequeueReusableCell(withIdentifier: "myCell",for: indexPath) as! MyCell
        let n = indexPath.row % 5
        var s = "Row \(indexPath.row)"
        for i in 0...n {
            s += "\n\(i)"
        }
        c.theLabel.text = s
        return c
    }

    private func scrollRectToVisible() {
        let index = tableView.numberOfRows(inSection: 0) - 1
        let indexPath = IndexPath(row: index,section: 0)
        let rect = tableView.rectForRow(at: indexPath)
        tableView.scrollRectToVisible(rect,animated: false)
    }

}

class MyCell: UITableViewCell {
    
    var theLabel = UILabel()
    
    override init(style: UITableViewCell.CellStyle,reuseIdentifier: String?) {
        super.init(style: style,reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() -> Void {
        theLabel.translatesAutoresizingMaskIntoConstraints = false
        theLabel.numberOfLines = 0
        theLabel.backgroundColor = .yellow
        contentView.addSubview(theLabel)
        let g = contentView.layoutMarginsGuide
        NSLayoutConstraint.activate([
            theLabel.topAnchor.constraint(equalTo: g.topAnchor),theLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor),theLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor),theLabel.bottomAnchor.constraint(equalTo: g.bottomAnchor),])
    }
    
}
,

内部viewDidLayoutSubviews

if tableView.numberOfRows(inSection: 0) != 0 {
  scrollRectToVisible()   
}

带有animated: false)

tableView.scrollRectToVisible(rect,animated: false)
,

我使用 tableView.scrollRectToVisible(rect,animated: false) 作为 animated 调用了 false,来自 viewDidAppear 方法并且结果符合预期。

我已经根据您上面的代码进行了复制和更改。在这里,我在您的方法 animated:bool 中添加了 scrollRectToVisible 作为参数以根据需要控制动画部分。

class ThemeTableViewController: UITableViewController {
    private var firstTime = true

    // added new parameter `animated`
    private func scrollRectToVisible(_ animated: Bool = true) {
        let theme = WeNoteOptions.theme
        if let index = Theme.allCases.firstIndex(of: theme) {
            let indexPath = IndexPath(row: index,section: 0)
            let rect = tableView.rectForRow(at: indexPath)

            // replaced true with `animated`
            tableView.scrollRectToVisible(rect,animated: animated)
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        if firstTime {
            firstTime.toggle()
            // animation = false.
            scrollRectToVisible(false)
        }
    }
}
,
Here consider itemCount = last item of your array

Add code in viewDidload method after your array contains data.

tableView.reloadData()
let indexPath = IndexPath(item: itemCount,section: 0)
print("indexPath",indexPath)
tableView.scrollToRow(at: indexPath,at: .none,animated: false)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。