自定义TableViewCell内的UICollectionView添加新项后无法调整尺寸
解决TableViewCell内UICollectionView点击“显示更多”不展开的问题
核心问题分析
- 重复添加约束导致冲突:每次点击按钮时重新调用
snp.makeConstraints添加高度约束,会和初始化时的约束冲突,AutoLayout无法正确应用新高度。 - TableView未更新cell高度:UICollectionView高度变化后,TableView不知道需要重新计算所在cell的高度,导致视觉上没有展开效果。
- 高度计算与布局参数不匹配:
countDynamicHeight中的间距计算需和UICollectionViewFlowLayout的minimumLineSpacing保持一致,否则高度计算不准确。
分步解决方案
1. 保存CollectionView高度约束,避免重复添加
在StudyDirectionsCell类中添加属性保存高度约束,后续仅更新约束的constant值:
class StudyDirectionsCell: UITableViewCell { // 新增:保存collectionView的高度约束 private var collectionViewHeightConstraint: Constraint? // 其余原有代码... }
修改prepareCollectionView方法,初始化时保存约束:
private func prepareCollectionView() { collectionView.snp.makeConstraints { make in make.leading.equalToSuperview().offset(16) make.top.equalTo(segmentedControl.snp.bottom).offset(25) make.trailing.equalToSuperview().inset(16) // 保存高度约束,而非每次重新创建 collectionViewHeightConstraint = make.height.equalTo(countDynamicHeight()).constraint } cellLabel.text = "Actual.StudyDirections".localized.uppercased() collectionView.showsVerticalScrollIndicator = false collectionView.showsHorizontalScrollIndicator = false collectionView.reloadData() collectionView.backgroundColor = .directionsCellBackground }
2. 更新handleShowMore方法,正确修改高度并通知TableView
@objc private func handleShowMore() { // 更新数据源 rowsToDisplay = selectedSegment == "bachelor" ? bachelor : college collectionView.reloadData() // 更新collectionView高度约束 collectionViewHeightConstraint?.update(offset: countDynamicHeight()) // 刷新collectionView布局 collectionView.collectionViewLayout.invalidateLayout() collectionView.layoutIfNeeded() // 通知TableView重新计算当前cell的高度 if let tableView = superview as? UITableView { tableView.beginUpdates() tableView.endUpdates() } }
3. 对齐FlowLayout间距与高度计算逻辑
确保UICollectionViewFlowLayout的minimumLineSpacing和countDynamicHeight中的间距一致:
private let collectionView: UICollectionView = { let layout = UICollectionViewFlowLayout() layout.scrollDirection = .vertical layout.minimumLineSpacing = 10 // 与countDynamicHeight中的间距匹配 // 若有item间距需求,可同时设置minimumInteritemSpacing let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout).prepareForAutoLayout() collectionView.register(StudyDirectionCell.self, forCellWithReuseIdentifier: StudyDirectionCell.identifier) collectionView.isScrollEnabled = false return collectionView }()
同时修正countDynamicHeight的行数计算(垂直方向每个item占一行,无需ceil):
func countDynamicHeight() -> CGFloat { let width: CGFloat = UIScreen.main.bounds.width - 32 let heightPerItem: CGFloat = width * 126.0 / 343.0 let itemCount = CGFloat(rowsToDisplay.count) let totalSpacing = CGFloat(max(0, rowsToDisplay.count - 1)) * 10 return heightPerItem * itemCount + totalSpacing }
4. 配置TableView支持自动高度计算
在包含该TableView的ViewController中,开启自动高度:
override func viewDidLoad() { super.viewDidLoad() // 其余初始化代码... tableView.estimatedRowHeight = 400 // 设置一个合理的预估高度 tableView.rowHeight = UITableView.automaticDimension }
内容的提问来源于stack exchange,提问作者laneboyandrew
相关产品推荐
相关产品推荐

