如何在不滚动表的情况下将行插入UITableView的顶部? [英] How to insert rows to the top of UITableView without scrolling the table?
问题描述
如何在不滚动表格的情况下将行插入UITableView的顶部?同样的,当你拖动重新加载Twitter上的新推文或whatsApp中的消息
How to insert rows to the top of UITableView without scrolling the table? The same like when when you drag to reload new tweets on twitter or messages in whatsApp
我尝试做另一部分begin / endUpdate,要求它滚动到第三个索引,但它不起作用。它总是滚动到tableView的顶部。我希望它保持与添加新行之前的位置相同。
I tried doing another section of begin/endUpdate asking it to scroll to the 3rd index, but it didn't work. It always scrolls to the top of the tableView. I want it to stay at the same position as it was before adding the new rows.
self.tableView.beginUpdates()
let indexPath = IndexPath(row: 3, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
self.tableView.endUpdates()
PS这是我真实项目中的一个示例项目,单元格的大小根据邮件大小而变化。
P.S. this is a sample project in my real project the cells varies in size based on the message size.
这是项目的链接:
https://github.com/akawther/TableView
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var tableView: UITableView!
var loadMore: UIRefreshControl!
var labels = ["A","B","C","D","E","F","G","H","I","J","K"]
override func viewDidLoad() {
super.viewDidLoad()
self.loadMore = UIRefreshControl()
self.loadMore.attributedTitle = NSAttributedString(string: "Pull to reload more")
self.loadMore.addTarget(self, action: #selector(ViewController.loadMoreChats), for: .valueChanged)
self.tableView.addSubview(self.loadMore)
// Do any additional setup after loading the view, typically from a nib.
}
func loadMoreChats() {
DispatchQueue.main.async(execute: {() -> Void in
self.tableView.beginUpdates()
self.labels.insert("3", at: 0)
self.labels.insert("2", at: 0)
self.labels.insert("1", at: 0)
let indexPaths = [
IndexPath(row: 0, section: 0),
IndexPath(row: 1, section: 0),
IndexPath(row: 2, section: 0),
]
self.tableView.insertRows(at: indexPaths, with: .top)
self.tableView.endUpdates()
self.loadMore.endRefreshing()
self.tableView.beginUpdates()
let indexPath = IndexPath(row: 3, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
self.tableView.endUpdates()
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return labels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! customCellTableViewCell
cell.label.text = labels[indexPath.row]
return cell
}
}
UPDATE#1:
我刚刚尝试了我的第二次更新/结束更新CATransaction,但仍显示顶部是1而不是我想要的A:
UPDATE #1: I have just tried it also by surrounding my second being/end update with CATransaction, but still the top displayed is 1 instead of A like I want:
CATransaction.begin()
self.tableView.beginUpdates()
CATransaction.setCompletionBlock { () -> Void in
let indexPath = IndexPath(row: 3, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
}
self.tableView.endUpdates()
CATransaction.commit()
UPDATE #2:
使用@beyowulf的答案更新github项目
UPDATE #2: The github project is updated with the answer from @beyowulf
推荐答案
此代码有效当 loadMoreChats
是按钮的目标时,我很好:
This code worked fine for me when loadMoreChats
was a target of a button:
func loadMoreChats() {
self.loadMore.endRefreshing()
self.labels.insert("3", at: 0)
self.labels.insert("2", at: 0)
self.labels.insert("1", at: 0)
self.tableView.reloadData()
let indexPath = IndexPath(row: 3, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
}
使用刷新控制案例 scrollToRow
被触发它的平移手势覆盖。
Using a refresh control cases the scrollToRow
to be overridden by the pan gesture that triggered it.
请注意,您引用的应用程序不会以这种方式使用刷新控制器,但是如果您坚持使用一个我认为您可以在编程方式滚动表视图时暂时禁用平移手势。类似于:
Note that the apps that you reference don't use a refresh controller in this way, but if you insist on using one I supposed you could disable the pan gesture briefly while you programmatically scroll the table view. Something like:
func loadMoreChats() {
self.loadMore.endRefreshing()
self.labels.insert("3", at: 0)
self.labels.insert("2", at: 0)
self.labels.insert("1", at: 0)
self.tableView.reloadData()
let indexPath = IndexPath(row: 3, section: 0)
self.tableView.scrollToRow(at: indexPath, at: .top, animated: false)
self.tableView.panGestureRecognizer.isEnabled = false
let when = DispatchTime.now() + 0.05
DispatchQueue.main.asyncAfter(deadline: when)
{
self.tableView.panGestureRecognizer.isEnabled = true
}
}
我发现这相当hacky并建议反对它。
I find this to be rather hacky and would recommend against it.
这篇关于如何在不滚动表的情况下将行插入UITableView的顶部?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!