动态设置UIScrollView的contentSize无效,求解决建议
解决UIScrollView contentSize设置无效的问题
嘿,我来帮你捋捋为啥你设置contentSize的代码没生效,再给你几个实用的解决办法~
先确认下你的视图层级
- ViewController
- View
- ScrollView
- 容器View
- TextView
- Label
- 其他子视图
- 容器View
- ScrollView
- View
你当前代码的问题
你用这段代码尝试设置contentSize,但没起作用:
let lastView : UIView! = scrollView.subviews.last let height = lastView.frame.size.height let pos = lastView.frame.origin.y let sizeOfContent = height + pos scrollView.contentSize.height = sizeOfContent
几个关键的解决思路
1. 找对正确的参考视图:用容器View的size来设置
你的ScrollView里先套了一个容器View,所有内容都在这个容器里,那容器View的frame.size才是整个滚动内容的真实大小,而不是去取ScrollView的最后一个子视图。试试改成这样:
// 假设容器View是scrollView的第一个子视图,或者你有IBOutlet直接引用它 guard let containerView = scrollView.subviews.first else { return } scrollView.contentSize = containerView.frame.size
如果是用Auto Layout的话,更推荐完全靠约束自动计算contentSize,不用手动写代码:
- 给容器View加这几个约束:
- 顶部、底部、左、右四个边和ScrollView的对应边缘完全对齐(约束优先级拉满)
- 容器View的宽度等于ScrollView的宽度(如果不需要水平滚动的话)
- 然后给容器里的TextView、Label等子视图设置连贯的垂直约束:比如TextView顶部贴容器顶部,Label顶部贴TextView底部,最后一个子视图的底部贴容器底部。这样容器View会自动算出自己的高度,ScrollView也会自动适配contentSize了。
2. 选对代码执行的时机
如果你的代码是放在viewDidLoad里,这时候视图还没完成布局,所有视图的frame都是xib/storyboard里的初始值,不是最终布局后的真实大小。建议把代码移到viewDidLayoutSubviews里,还要注意避免重复执行:
var hasSetContentSize = false override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() // 只设置一次,避免每次布局都重复执行 guard !hasSetContentSize else { return } guard let containerView = scrollView.subviews.first else { return } scrollView.contentSize = containerView.frame.size hasSetContentSize = true }
3. 检查子视图的布局是否正确
如果容器View里的子视图约束没设置好,比如最后一个子视图的底部没贴容器View的底部,那就算你取最后一个子视图的位置计算,得到的高度也会比真实内容矮,导致contentSize设置不对。先确保所有子视图的垂直约束是连贯的,从容器顶部到底部形成完整的约束链。
内容的提问来源于stack exchange,提问作者Md. Mostafizur Rahman
相关产品推荐
相关产品推荐

