Ios UITableView单元格折叠动画看起来不好
我在使细胞塌陷动画看起来始终平滑时遇到问题 我的形象胜过千言万语。以下是相同表视图的两个GIF: 折叠对单元格“6”非常有效,但对单元格“5”无效。看起来整个UITableView内容在执行折叠动画之前都会跳起来 我不是在使用UITableView的Ios UITableView单元格折叠动画看起来不好,ios,swift,uitableview,ios11,Ios,Swift,Uitableview,Ios11,我在使细胞塌陷动画看起来始终平滑时遇到问题 我的形象胜过千言万语。以下是相同表视图的两个GIF: 折叠对单元格“6”非常有效,但对单元格“5”无效。看起来整个UITableView内容在执行折叠动画之前都会跳起来 我不是在使用UITableView的行高的UITableView自动维度。相反,我通过tableView(\utableview:UITableView,heightForRowAt indexath:indexPath)方法提供行高,并使用tableView的beginUpdat
行高的UITableView自动维度。相反,我通过tableView(\utableview:UITableView,heightForRowAt indexath:indexPath)
方法提供行高,并使用tableView的beginUpdates
/endUpdates
展开/折叠单元格。如您所见,我还使用tableView.scrollToRow(at:indepath,at:.none,animated:true)滚动到展开的行
(但仅限于展开时,所以这可能无关紧要)
UITableViewController的子类嵌入在带有大标题和搜索栏的UINavigationController中(此处不可见,因为内容向下滚动)。UINavigationController嵌入在UITabBarController中
下面是相关的展开/折叠部分。当传递nilindepath
参数时,已经扩展的单元格将崩溃
func expandRow(at indexPath: IndexPath?) {
selectedIndexPath = indexPath
tableView.beginUpdates()
tableView.endUpdates()
if let ip = indexPath {
tableView.scrollToRow(at: ip, at: .none, animated: true)
}
}
此方法计算行高,并由tableView(\u0:heightForRowAt:)
和tableView(\u0:estimatedHeightForRowAt:)
调用:
以下是GitHub回购协议:
你知道如何改进吗
此问题是尺寸敏感问题(在屏幕大小不同的设备上执行相同步骤后,此问题可能无法再现)。这是用iOS 11.3在iPhone7模拟器上录制的
编辑1:
保留自动滚动到展开单元格的功能非常重要。您正在滚动到展开的行,这使得UITableView有点跳跃
下面是一个重构的expandRow(at:)
方法:
func expandRow(at indexPath: IndexPath?) {
self.contentOffset = self.tableView.contentOffset
selectedIndexPath = indexPath
tableView.beginUpdates()
tableView.endUpdates()
if let contentOffset = self.contentOffset {
tableView.contentOffset = contentOffset
}
}
您还需要向控制器添加var contentOffset:CGPoint?
属性
更新
我错了,你不需要把selectedIndexPath=indexPath
btwbeginUpdate()
和endUpdates()
方法。更新的代码示例我能够通过对展开方法的细微更改使其变得平滑:
func expandRow(at indexPath: IndexPath?) {
selectedIndexPath = indexPath
tableView.beginUpdates()
tableView.endUpdates()
if let ip = indexPath {
tableView.scrollToRow(at: ip, at: .middle, animated: true)
}
}
我有个主意。我不确定诀窍是否像我想的那样有效
可折叠表格的一项功能是,当表格视图展开或折叠时,其高度将发生变化
如果使用从UITableView继承的自定义视图,则可以覆盖视图的属性contentSize和contentOffset。
通过重写这两个属性,我们可以使表视图停止,暂时禁用滚动
var contentSizeChanging: Bool = false
override var contentSize: CGSize {
willSet {
contentSizeChanging = true
}
didSet {
contentSizeChanging = false
}
}
override var contentOffset: CGPoint {
get {
return super.contentOffset
}
set(newValue) {
if contentSizeChanging { return }
super.contentOffset = newValue
}
}
在为每行单击调整我的行高时出现此问题。与@Taras的答案几乎相同,尽管在这里,在分配保存的contentOffset之前,需要先删除动画。希望这有帮助:)
你认为这两行带有.beginUpdate()
和.endUpdates()
的代码在做什么?据我所知,这是一种众所周知的技术,可以使表格视图以动画方式更新单元格高度。单元格高度的计算方法如下:(我粘贴了原始问题,因为注释中没有代码格式)@AleksanderMaj您找到解决方案了吗?@guru不幸的是,没有。我很久以前就放弃了此解决方案。此解决方案将导致大多数顶部和底部单元格意外跳跃感谢您的回答,但正如@TarasChernyshenko指出的,它引入了其他问题。感谢您的回复。滚动部分仅在展开时执行(即indepath!=nil
),它对折叠单元格没有影响。这不是问题的一部分。您的响应中的contentOffset部分根本不起作用。展开单元格“5”,然后手动滚动,使其底边与选项卡栏顶部对齐。然后再次点击“5”将其折叠。它仍然在跳跃:
var contentSizeChanging: Bool = false
override var contentSize: CGSize {
willSet {
contentSizeChanging = true
}
didSet {
contentSizeChanging = false
}
}
override var contentOffset: CGPoint {
get {
return super.contentOffset
}
set(newValue) {
if contentSizeChanging { return }
super.contentOffset = newValue
}
}
func expandRow() {
let savedContentOffset = tableView.contentOffset
tableView.beginUpdates()
tableView.endUpdates()
tableView.layer.removeAllAnimations()
tableView.setContentOffset(savedContentOffset, animated: false)
}