_adjustContentOffsetIfNecessary - UIScrollView 自动滚动到顶部

Posted

技术标签:

【中文标题】_adjustContentOffsetIfNecessary - UIScrollView 自动滚动到顶部【英文标题】:_adjustContentOffsetIfNecessary - UIScrollView automatically scrolls to top 【发布时间】:2014-05-23 07:58:02 【问题描述】:

ios 7 上。 我有导航控制器,并在堆栈顶部推送了一个新的 VC。

那个新的 VC 有一个 UIScrollView 填充 VC 的根视图并垂直滚动。如果我向下滚动一点,然后尝试使用“滑动返回”/“滑动弹出”手势,垂直滚动视图首先滚动到顶部,然后识别 interactivePopGesture,我可以拖动顶部的 VC左右堆叠。

为什么会这样? 我希望防止我的滚动视图在识别“滑动返回”手势之前自动滚动到顶部。 我该怎么做?

更新#1:

当我创建一个新的 xcode 项目时,我似乎无法重现这个错误,所以这肯定是我在原始项目中的错误。找到原因后会更新。

更新 #2:

当 interactivePopGesture 被识别时,setContentOffset 方法在我的垂直滚动视图上被调用。在调试时,我看到setContentOffset 是从UIScrollViewInternal _adjustContentOffsetIfNecessary 调用的。

更新 #3:

同样的问题发生在以下场景中: 我在垂直 UIScrollView 中有 UITextFields。当按下某个 UITextField 时,会出现一个键盘。当我想以交互方式关闭键盘时(通过在键盘上拖动滚动视图),在我释放拖动后,会发生故障。 UIScrollView 的内容偏移量暂时设置为零,然后设置回原始内容偏移量并继续动画。 contentOffset 这个不需要的设置也被UIScrollViewInternal _adjustContentOffsetIfNecessary 调用。

我继续用我自己的 UIScrollView 子类替换了这两种情况下的 UIScrollView。在该子类中,我将私有方法 -(void) _adjustContentOffsetIfNecessary 重写为空的 void 方法。我的两个问题都解决了,我找不到任何负面后果。这不是一个解决方案,我不会使用这种方法,因为我不知道我到底做了什么。

【问题讨论】:

可能与iOS7上UIViewController的setAutomaticallyAdjustsScrollViewInsets api有关 我自动设置AdjustsScrollViewInsets = NO;在我认为可能与情况相关的每个视图控制器上。它没有帮助。 我也遇到了这个问题。我手动将 contentOffset 设置为 (0,-64),但 _adjustContentOffsetIfNecessary 再次将其更改为 -108。使困惑。有更新吗? 不,还没有更新...如果我有时间,我会尝试在示例应用程序中重新创建问题,然后在此处发布指向 git 存储库的链接... 你解决了这个问题了吗?我在使用自动布局时也遇到了这个问题... 【参考方案1】:

我在 Twitter 上找到了一个关于此的 interesting discussion。虽然这不是我的情况,但它可能会对某人有所帮助:

Is there some trick to bring UINavigationController to not mess with a UIScrollView  (_adjustContentOffsetIfNecessary)?

@steipete Searching for the same thing and came across your tweet. I set contentOffset but it resets back to -64 (ios7). Did you find a fix?
 @errthling Add a dummy view as first subview. It won’t look further.
 @steipete Wow – that worked. I've been struggling with it for days. Thanks for that and everything else you put out there! :)
 @errthling happy to help!

@steipete did you find an answer to this, 2 years ago? =D my scrollview's contentOffset is reset when I push a new viewcontroller..
 @manuelmaly Yeah. Changed the view hierarchy so the scroll view is not the main view and not the first subview, and UIKit stops messing.
 @steipete oO i hacked it in the meantime by blocking setContentOffset before pushViewController is called. your solution seems cleaner tho

【讨论】:

这似乎不适用于 iOS 12.3。尝试在 UICollectionView 周围的所有位置添加虚拟视图(这样它就不是主要的,也不是第一个,不是最后一个,...),但是每次重新加载 collectionView 时都会调用 _adjustContentOffsetIfNecessary。【参考方案2】:

我在 iOS 14 中遇到了同样的问题。看起来没有正常的方法来阻止_adjustContentOffsetIfNecessary 的调用。在问题视图中覆盖 didMoveToWindow() 对我有帮助

override func didMoveToWindow() 
    super.didMoveToWindow()
    // window == nil when new screen pushed
    if window == nil 
        // Set correct offset that was before
    

【讨论】:

或者您可以覆盖 contentOffset 属性保护窗口!= nil else return super.contentOffset = newValue @clatt 是的,如果你已经使用了继承 UIScrollView 的类,那也可以。我提供的解决方案允许使用标准 UIScrollView 并在指定的 UIView 元素中定义偏移行为【参考方案3】:

将 UIViewController 与 UITableView 一起使用,而不是 UITableViewController。它解决了我的问题:)

【讨论】:

以上是关于_adjustContentOffsetIfNecessary - UIScrollView 自动滚动到顶部的主要内容,如果未能解决你的问题,请参考以下文章

函数参数

多重背包

合租房合同模板

启动代码分析 02

ACM数论 求幂乘

Windows下虚拟机安装Mac OS X —– VM12安装Mac OS X 10.11