UIScrollView嵌套两个动态UICollectionView,如何实现整体自适应滚动?
嘿,这个需求我之前做过类似的,其实核心就是让外层UIScrollView的内容高度由内部两个UICollectionView的总高度来驱动,同时禁用两个CollectionView自身的滚动,让它们跟着外层ScrollView一起动。我给你一步步说具体实现:
核心实现步骤
1. 基础布局与滚动设置
首先要确保两个关键设置:
- 把两个UICollectionView的
isScrollEnabled都设为false,这样它们不会自己滚动,完全交由外层UIScrollView控制。 - 给外层UIScrollView设置正确的约束:让它的
top、left、right、bottom(或安全区域)和父视图完全对齐,不要给ScrollView设置固定高度,它的高度由父视图决定,内容高度则由内部子视图撑开。
2. 让下方UICollectionView高度自适应内容
要实现条目增加时高度自动变化,需要两步:
第一步:让Cell自动计算高度
如果用的是UICollectionViewFlowLayout,在viewDidLoad里开启自动尺寸计算:
if let flowLayout = bottomCollectionView.collectionViewLayout as? UICollectionViewFlowLayout { // 开启自动计算cell高度,前提是cell内部约束能确定自身高度 flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize }
⚠️ 这里要注意:你的Cell内部约束必须完整,比如UILabel的top/left/right/bottom都和Cell的contentView对齐,这样系统才能算出Cell的准确高度。
第二步:动态更新CollectionView的高度约束
给下方的UICollectionView添加一个高度约束的IBOutlet(比如命名为bottomCollectionViewHeightConstraint),初始值可以设为0或者预估高度。然后有两种方式更新这个约束:
方式一:数据更新后手动刷新
每次给下方CollectionView添加新数据后,调用刷新并更新高度:
func addNewItemsToBottomCollection(_ newItems: [YourItemModel]) { dataSourceArray.append(contentsOf: newItems) bottomCollectionView.reloadData() // 等待布局完成后更新高度约束 DispatchQueue.main.async { self.bottomCollectionViewHeightConstraint.constant = self.bottomCollectionView.contentSize.height self.view.layoutIfNeeded() } }
方式二:用KVO自动监听内容尺寸变化
如果想更自动化,不用每次手动调用,可以监听CollectionView的contentSize属性:
override func viewDidLoad() { super.viewDidLoad() // ...其他初始化代码 bottomCollectionView.addObserver(self, forKeyPath: "contentSize", options: [.new], context: nil) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if keyPath == "contentSize", let collectionView = object as? UICollectionView, collectionView == bottomCollectionView { bottomCollectionViewHeightConstraint.constant = collectionView.contentSize.height view.layoutIfNeeded() } } deinit { // 记得移除观察者,避免内存泄漏 bottomCollectionView.removeObserver(self, forKeyPath: "contentSize") }
3. 确保外层ScrollView自动扩展高度
给两个CollectionView设置垂直排列的约束:
- 上方CollectionView:
top对齐ScrollView的top,left/right对齐ScrollView的对应边,设置固定高度(如果它的内容高度固定),或者也用上面的方法做自适应高度。 - 下方CollectionView:
top对齐上方CollectionView的bottom,left/right对齐ScrollView的对应边,bottom对齐ScrollView的bottom。
这样一来,当下方CollectionView的高度因条目增加而变大时,外层ScrollView的contentSize会自动被撑开,整个视图就能正常向上滚动,上方的CollectionView也会跟着一起滚动了。
内容的提问来源于stack exchange,提问作者kamenr
相关产品推荐
相关产品推荐

