有一个我无法解决的问题,即-我要为向表中添加新单元格(tableView.insertRows)的平滑动画进行战斗。下面的视频显示了在开始时所有单元格是如何疯狂抽动的,我对代码进行了编码:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if (destinationData?[indexPath.row]) != nil {
return 110
} else {
return 95
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if (destinationData?[indexPath.row]) != nil {
if(indexPath.row + 1 >= (destinationData?.count)!) {
expandCell(tableView: tableView, index: indexPath.row)
}
else {
if(destinationData?[indexPath.row+1] != nil) {
expandCell(tableView: tableView, index: indexPath.row)
// Close Cell (remove ExpansionCells)
} else {
contractCell(tableView: tableView, index: indexPath.row)
}
}
}
}
private func expandCell(tableView: UITableView, index: Int) {
if let infoMain = destinationData?[index]?.infoMain {
for i in 1...infoMain.count {
destinationData?.insert(nil, at: index + 1)
tableView.insertRows(at: [IndexPath(row: index + i, section: 0)] , with: .bottom)
}
}
}
private func contractCell(tableView: UITableView, index: Int) {
if let infoMain = destinationData?[index]?.infoMain {
for _ in 1...infoMain.count {
destinationData?.remove(at: index + 1)
tableView.deleteRows(at: [IndexPath(row: index + 1, section: 0)], with: .top)
}
}
}
答案 0 :(得分:1)
通常,UITableView
在无法轻松估计单元格的正确高度时开始跳跃。
要解决此问题,请先通过tableView(_, estimatedHeightForRowAt: ) -> CGFloat
方法返回正确的高度
第二点,您可以存储当前的contentOffset
self.tableView.beginUpdates()
let contentOffset = self.tableView.contentOffset
self.tableView.insertRows(at: [indexPath], with: .automatic)
self.tableView.contentOffset = contentOffset
self.tableView.endUpdates()
更新
因此,如果需要插入和删除几个索引,则需要在单个beginUpdates()endUpdates()
块中执行此操作
尝试将您的代码更改为此:
if let infoMain = destinationData?[index]?.infoMain {
self.tableView.beginUpdates()
let contentOffset = self.tableView.contentOffset
var indexes: [IndexPath] = []
for i in 1...infoMain.count {
destinationData?.insert(nil, at: index + 1)
indexes.append(IndexPath(row: index + i, section: 0))
}
tableView.insertRows(at: indexes, with: .bottom)
self.tableView.contentOffset = contentOffset
self.tableView.endUpdates()
}
if let infoMain = destinationData?[index]?.infoMain {
self.tableView.beginUpdates()
let contentOffset = self.tableView.contentOffset
for _ in 1...infoMain.count {
destinationData?.remove(at: index + 1)
indexes.append(IndexPath(row: index + i, section: 0))
}
tableView.deleteRows(at: indexes, with: .top)
self.tableView.contentOffset = contentOffset
self.tableView.endUpdates()
}
答案 1 :(得分:1)
如果您对表视图内容进行了多个动画更改,则应将它们全部包装到tableView.beginUpdates() ... tableView.endUpdates()
个调用中。
您正在for...in
循环中进行多次插入或删除。
将您的代码更改为此:
private func expandCell(tableView: UITableView, index: Int) {
if let infoMain = destinationData?[index]?.infoMain {
tableView.beginUpdates()
for i in 1...infoMain.count {
destinationData?.insert(nil, at: index + 1)
tableView.insertRows(at: [IndexPath(row: index + i, section: 0)] , with: .bottom)
}
tableView.endUpdates()
}
}
private func contractCell(tableView: UITableView, index: Int) {
if let infoMain = destinationData?[index]?.infoMain {
tableView.beginUpdates()
for _ in 1...infoMain.count {
destinationData?.remove(at: index + 1)
tableView.deleteRows(at: [IndexPath(row: index + 1, section: 0)], with: .top)
}
tableView.endUpdates()
}
}
一种更好的方法是累积IndexPath
您要更改为数组并立即执行所有插入或删除操作:
private func expandCell(tableView: UITableView, index: Int) {
if let infoMain = destinationData?[index]?.infoMain {
var indexesToInsert = [IndexPath]()
for i in 1...infoMain.count {
destinationData?.insert(nil, at: index + 1)
indexesToInsert.append(IndexPath(row: index + i, section: 0))
}
tableView.insertRows(at: indexesToInsert, with: .bottom)
}
}
private func contractCell(tableView: UITableView, index: Int) {
if let infoMain = destinationData?[index]?.infoMain {
var indexesToDelete = [IndexPath]()
for _ in 1...infoMain.count {
destinationData?.remove(at: index + 1)
indexesToDelete.append(IndexPath(row: index + 1, section: 0))
}
tableView.deleteRows(at: indexesToDelete, with: .top)
}
}