Unable to setContentOffset in scrollViewDidEndDrag

2019-02-25 04:17发布

I am attempting to modify the contentOffset of my scroll within the following delegate method:

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate

I have tried both of the following:

[UIView animateWithDuration:.2 animations:^ {
   [scrollView setContentOffset:CGPointZero animated:NO];
}];

and

[UIView animateWithDuration:.2 animations:^ {
   CGRect svBounds = self.bounds;
   svBounds.origin.y = 0;
   self.bounds = svBounds; 
}];

The problem is that although this changes the offset right away (proven by logs after the animation is complete), it doesn't change the visible scroll location. This is further proven by subsequent delegate methods of my scroll view which indicate that the bounds have indeed not changed at all. Meaning that the y location is not 0.

Is it forbidden to change the content offset in this particular delegate method? If so, when is it possible for me to change the offset? I'm trying to perform an animation of returning the visible scroll area to the top once the user finishes dragging (after a certain amount).

Thanks!

3条回答
萌系小妹纸
2楼-- · 2019-02-25 04:36

what i did eventually is dispatching again to the main queue. meaning:

-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
NSLog(@"END DRAG");
CGFloat yVelocity = [scrollView.panGestureRecognizer velocityInView:scrollView].y;
if (yVelocity < 0) {
    NSLog(@"Up");
} else {
    NSLog(@"Down");
}

if (yVelocity < 0 && scrollView.contentOffset.y < -100 && scrollView.contentOffset.y > -200) //UP - Hide
{
    NSLog(@"hiding");
    dispatch_async(dispatch_get_main_queue(), ^{
        [scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
    });
}
else if (yVelocity > 0 && scrollView.contentOffset.y < -100) //DOWN - Show
{
    NSLog(@"showing");
    dispatch_async(dispatch_get_main_queue(), ^{
        [scrollView setContentOffset:CGPointMake(0, -300) animated:YES];
    });
}

}

and it actually works :-)

查看更多
啃猪蹄的小仙女
3楼-- · 2019-02-25 04:41

Depending on the effect you are trying to achieve, you may have more luck with this delegate method:

- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset

You can choose what target content offset you want to use for the scroll view to decelerate to once the user stops dragging.

查看更多
混吃等死
4楼-- · 2019-02-25 04:56

You should "nil" your scrollView delegate before animation, set content offset in scrollViewDidEndDragging:willDecelerate: will cause repeat delegation.

self.scrollView.delegate = nil;
[self.scrollView setContentOffset:CGPointMake(x, y) animated:YES];
self.scrollView.delegate = self;
查看更多
登录 后发表回答