Swift中设置UIScrollView的contentInset不生效问题如何解决?
问题根因
- 你在
layoutSubviews中修改contentInset的逻辑会被多次触发,多次赋值过程中会出现数值反复,且修改contentInset后UIScrollView默认不会主动调整当前可视区域,导致视觉上没有变化,需要手动滑动触发刷新。 someView的frame计算时机不准确,layoutSubviews调用时可能someView的布局还未完成,拿到的frame值有误。
解决方案
直接通过RxSwift监听someView的显隐状态,状态变更时主动刷新布局后修改contentInset,同时调整contentOffset触发UIScrollView可视区域刷新:
- 首先移除
layoutSubviews中修改curtainView.contentInset的相关代码 - 添加Rx监听逻辑,代码示例如下:
// 监听someView的hidden属性变化,distinctUntilChanged避免重复触发 someView.rx.observe(Bool.self, "hidden") .distinctUntilChanged() .subscribe(onNext: { [weak self] isHidden in guard let self = self else { return } // 先强制完成当前视图层级的所有布局,确保拿到someView的正确frame self.view.layoutIfNeeded() let topInset = isHidden ? 0 : self.someView.frame.maxY // 赋值contentInset self.curtainView.contentInset = UIEdgeInsets(top: topInset, left: 0, bottom: 0, right: 0) // 同步调整contentOffset,触发scrollView可视区域刷新,无需手动滑动 self.curtainView.contentOffset = CGPoint(x: 0, y: -topInset) }) .disposed(by: disposeBag)
- 避免系统自动调整scrollView的inset和手动设置的数值冲突,添加如下配置:
if #available(iOS 11.0, *) { curtainView.contentInsetAdjustmentBehavior = .never } else { // iOS 11以下对应ViewController的属性配置 automaticallyAdjustsScrollViewInsets = false }
补充说明
如果你是通过自定义的Rx序列控制someView的显隐,可直接使用该序列替代上述KVO监听hidden属性的逻辑,准确性更高。
内容的提问来源于stack exchange,提问作者Сергей Солнышкин
相关产品推荐
相关产品推荐

