Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UIScrollView setContentInset causes scroll skip in ios8

I'm having a problem when creating a pull to refresh mechanism at the bottom of a scrollview. The code works perfectly smoothly in iOS7, but in iOS8 the scrollview instantly skips up before then animating to the correct position.

I'm tracking the scroll until it has rubber-banded beyond kPullToRefreshHeightPX (in my case this is 40px), and setting a flag to then inset on release, and trigger a content refresh.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (_webShouldInsetScrollView == NO && (scrollView.contentOffset.y > ((scrollView.contentSize.height - scrollView.frame.size.height) + kPullToRefreshHeightPX)))
    {
        _webShouldInsetScrollView = YES;
    }
}

If on end dragging we have dragged beyond our refresh distance, then we inset (and run our little refresh animation) and show the next results page.

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    if (_webShouldInsetScrollView)
    {
        [UIView animateWithDuration:0.2 animations:^{
                [scrollView setContentInset:UIEdgeInsetsMake(0.0f, 0.0f, kPullToRefreshHeightPX, 0.0f)];
        } completion:^(BOOL finished) {
        }];

        [self performSelector:@selector(showNextResultsPage) withObject:nil afterDelay:1.0f];
    }
}

I've read other issues with UIScrollViews in iOS8, one of which talked about automaticallyAdjustsScrollViewInsets being set to false in iOS7, but now true by default in iOS8, but this has no effect on the above code. Has anyone else had a similar experience and figured a way round it?

like image 393
Afox Avatar asked Feb 12 '23 23:02

Afox


2 Answers

fix that issue,:D

CGPoint offset = scrollView.contentOffset;
[scrollView setContentInset:UIEdgeInsetsMake(topInset, 0, 0, 0)];
scrollView.contentOffset = offset;
like image 193
ping Avatar answered Feb 14 '23 12:02

ping


We have exactly the same issue...

After digging deeper I have seen, that somehow initially the target inset is set somewhere:

let's say I pull down the tableView from 200 to 500 - on scrollViewDidEndDragging I trigger the animation like this:

 [UIView animateWithDuration:0.2
                          delay:0
                        options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState
                     animations:^{
                         scrollView.contentInset = targetInset;
                     }
                     completion:nil];

    [self sendActionsForControlEvents:UIControlEventValueChanged];

Instead of animating smoothly from 500 back to -let's say- 250, the targetValue (250) is set once before the correct animated values are set...

My Workaround has been to set a animation-flag before starting the animation. I reset it in the complete-block... The scroller checks this flag and sets the targetValue only if the animation is over:

_isAnimatingInset = YES;
_currentTopInsetTarget = targetInset.top;

 [UIView animateWithDuration:0.2
                          delay:0
                        options:UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState
                     animations:^{
                         scrollView.contentInset = targetInset;
                     }
                     completion:^(BOOL finished) {
                         //Workaround for a iOS8-Bug see property-comment for further infos
                         _isAnimatingInset = NO;
                         scrollView.contentInset = targetInset;
                     }];

    [self sendActionsForControlEvents:UIControlEventValueChanged];

This minimizes the effect, but unfortunately at this moment I cannot prevent the setting of this wrong value (instead I reset it to the previous what also leads to a small hickUp in the animation...)

like image 24
niggeulimann Avatar answered Feb 14 '23 12:02

niggeulimann