Setting contentOffset programmatically triggers scrollViewDidScroll

前端 未结 6 1295
别跟我提以往
别跟我提以往 2020-12-04 09:02

I\'ve got a a few UIScrollView on a page. You can scroll them independently or lock them together and scroll them as one. The problem occurs when they are locke

相关标签:
6条回答
  • 2020-12-04 09:38

    This is not a direct answer to the question, but if you are getting what appear to be spurious such messages, it can ALSO be because you are changing the bounds. I am using some Apple sample code with a "tilePages" method that removes and adds subview to a scrollview. This infrequently results in additional scrollViewDidScroll: messages called immediately, so you get into a recursion which you for sure didn't expect. In my case I got a nasty impossible to find crash.

    What I ended up doing was queuing the call on the main queue:

    - (void)scrollViewDidScroll:(UIScrollView *)scrollView
    {
        if(scrollView == yourScrollView) {
            // dispatch fixes some recursive call to scrollViewDidScroll in tilePages (related to removeFromSuperView)
            // The reason can be found here: http://stackoverflow.com/questions/9418311
            dispatch_async(dispatch_get_main_queue(), ^{ [self tilePages]; });
        }
    }
    
    0 讨论(0)
  • 2020-12-04 09:41

    What about using existing properties of UIScrollView?

    if(scrollView.isTracking || scrollView.isDragging || scrollView.isDecelerating) {
        //your code
    }
    
    0 讨论(0)
  • 2020-12-04 09:41

    Simplifying @Tark's answer, you can position the scrollview without firing scrollViewDidScroll in one line like this:

    scrollView.bounds.origin = CGPoint(x:0, y:100); // whatever values you'd like
    
    0 讨论(0)
  • 2020-12-04 09:46

    Try

    id scrollDelegate = scrollView.delegate;
    scrollView.delegate = nil;
    scrollView.contentOffset = point;
    scrollView.delegate = scrollDelegate;
    

    Worked for me.

    0 讨论(0)
  • 2020-12-04 09:49

    Another approach is to add some logic in your scrollViewDidScroll delegate to determine whether or not the change in content offset was triggered programatically or by the user's touch.

    • Add an 'isManualScroll' boolean variable to your class.
    • Set its initial value to false.
    • In scrollViewWillBeginDragging set it to true.
    • In your scrollViewDidScroll check to see that is it true and only respond if it is.
    • In scrollViewDidEndDecelerating set it to false.
    • In scrollViewWillEndDragging add logic to set it to false if the velocity is 0 (as scrollViewDidEndDecelerating won't be called in this case).
    0 讨论(0)
  • 2020-12-04 09:51

    It is possible to change the content offset of a UIScrollView without triggering the delegate callback scrollViewDidScroll:, by setting the bounds of the UIScrollView with the origin set to the desired content offset.

    CGRect scrollBounds = scrollView.bounds;
    scrollBounds.origin = desiredContentOffset;
    scrollView.bounds = scrollBounds;
    
    0 讨论(0)
提交回复
热议问题