UIScrollView禁用isScrollEnabled时整体视图异常上移问题求解
UIScrollView禁用滚动时上移问题解答
问题原因
- 第一是UIScrollView默认的
contentInsetAdjustmentBehavior为.automatic,系统会在滚动功能启用时自动添加顶部内边距,让内容避开导航栏和状态栏;当你禁用滚动时,系统会停止自动适配,顶部内边距突然消失,内容直接顶到状态栏/导航栏下方,就是你看到的上移效果。 - 第二是切换
isScrollEnabled时,系统会自动将contentOffset校正到当前contentSize对应的合法取值范围,当你隐藏StackView后contentSize变小,合法的offset范围也会变化,自动校正的过程就会触发视图偏移。 - 你当前的修复代码时机是在系统自动偏移之后才调用,且开了
animated: true,所以会出现先上移再回落的闪烁。
修复方案
- 首先固定ScrollView的内边距适配规则,禁止系统自动修改内边距,手动设置顶部内边距为导航栏+状态栏总高度:
// 关闭系统自动内边距调整 scrollView.contentInsetAdjustmentBehavior = .never // 如果使用Interface Builder搭建界面,也可以直接在ScrollView的属性面板中将「Content Inset」改为「Never」 let statusBarHeight = view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0 let navBarHeight = navigationController?.navigationBar.frame.height ?? 0 let totalTopInset = statusBarHeight + navBarHeight // 手动设置内边距和滚动条内边距 scrollView.contentInset = UIEdgeInsets(top: totalTopInset, left: 0, bottom: 0, right: 0) scrollView.scrollIndicatorInsets = scrollView.contentInset
- 调整StackView显隐和滚动开关的操作顺序,先更新布局再修改offset,最后调整滚动开关,避免动画冲突:
// 切换StackView显隐 targetStackView.isHidden.toggle() // 强制触发布局更新,拿到最新的contentSize scrollView.layoutIfNeeded() // 无动画设置正确的offset,避免闪烁 scrollView.setContentOffset(CGPoint(x: 0, y: -totalTopInset), animated: false) // 根据内容高度判断是否需要启用滚动 scrollView.isScrollEnabled = scrollView.contentSize.height > (scrollView.bounds.height - totalTopInset - scrollView.contentInset.bottom)
内容的提问来源于stack exchange,提问作者pedroeusebio
相关产品推荐
相关产品推荐

