我尝试为表格视图部分实现折叠/展开系统。当用户敲击节标题时,当在同一节标题上再敲击一次时,它将在节中插入单元格,然后它将删除节中的单元格,从而产生“折叠”效果。
问题是当我尝试从底部开始扩展两个以上的部分时。点击部分中至少有一个单元格将没有动画的整个内容移动到下部位置。
我使用代码和RxDataSource的自动布局。
这是我绑定数据源的方式:
let dataSourceForPurchasersList = RxTableViewSectionedAnimatedDataSource<AnimatableSectionModel<ExpandableSectionModel, CustomerCellModel>>(configureCell: { (dataSource, tableView, indexPath, cellModel) -> UITableViewCell in
let cell = tableView.dequeueReusableCell(withIdentifier: GuestTableViewCell.reuseIdentifier, for: indexPath) as? GuestTableViewCell
cell?.setupCell(model: cellModel)
return cell ?? UITableViewCell()
})
viewModel.dataSourceBehaviorPurchasersList
.bind(to: self.ordersTableView.rx.items(dataSource: dataSourceForPurchasersList))
.disposed(by: self.disposeBag)
这是我处理部分展开的方式:
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let viewModel = self.viewModel else { return nil }
let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: CustomersSectionHeader.reuseIdentifier) as? CustomersSectionHeader
...
guard let models = try? modelsBehavior.value() else { return nil }
let dataSourceSectionModel = models[section]
header?.configView(model: dataSourceSectionModel)
header?.tapClosure = { [weak modelsBehavior, weak header] in
dataSourceSectionModel.expanded = !dataSourceSectionModel.expanded
header?.updateSelectorImageView()
modelsBehavior?.onNext(models)
}
return header
}
@edit
解决方案:
我观察到,通过实现scrollViewDidScroll(_ scrollView: UIScrollView)
函数,内容的移位等于节标题的高度,它取决于表视图内部逻辑。我将节标题的headerHeight和estimateHeight设置为相等的值,然后使用以下代码:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let divValue: CGFloat
if self.guestsTableView.delegate === scrollView.delegate {
divValue = self.guestsTableView.estimatedSectionHeaderHeight
} else {
divValue = self.ordersTableView.estimatedSectionHeaderHeight
}
let diff = abs(self.scrollViewOffsetLastY - scrollView.contentOffset.y)
let rest = diff.truncatingRemainder(dividingBy: divValue)
if rest == 0 {
scrollView.contentOffset.y = self.scrollViewOffsetLastY
}
self.scrollViewOffsetLastY = scrollView.contentOffset.y
}