Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

contentOffset of UIScrollView during rotation

I want to manually update the contentOffset of an UIScrollView during rotation changes. The scroll view fills the screen and has flexible width and flexible height.

I'm currently trying to update the contentOffset in willRotateToInterfaceOrientation, like this:

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [Utils logPoint:myScrollView.contentOffset tag:@"initial"];
    myScrollView.contentOffset = CGPointMake(modifiedX, modifiedY);
    [Utils logPoint:myScrollView.contentOffset tag:@"modified"];
}

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
    [Utils logPoint:myScrollView.contentOffset tag:@"final"];
}

However, the final value is not the modified value, and it kinda seems to be influenced by it, but it's not evident to me how.

These are some of the results that I get:

initial: (146.000000;-266.000000)
modified: (81.000000;-108.000000)
final: (59.000000;-0.000000)

initial: (146.000000;-266.000000)
modified: (500.000000;500.000000)
final: (59.000000;500.000000)

initial: (146.000000;-266.000000)
modified: (-500.000000;-500.000000)
final: (-0.000000;-0.000000)

How do I update the contentOffset of a scroll view during a rotation change?

like image 894
hpique Avatar asked Sep 05 '10 19:09

hpique


3 Answers

Converting my comment to an answer :)

Try changing contentOffset from within willAnimateRotationToInterfaceOrientation:duration: instead. An animation block should be in place by then, and the OS regards your changes to contentOffset as belonging to the changes caused by the rotation.

If you change contentOffset before, it looks like the system doesn't respect these changes as belonging to the rotation, and still applies rotation-resizing, this time starting from your new dimensions.

like image 139
Pascal Avatar answered Nov 05 '22 07:11

Pascal


Following snippets does the trick when paging is enabled on UIScrollView and page offset is to be maintained.

Declare a property which will calculate position of currentPage before rotation, and set it to -1 in viewDidLoad

@property (assign, nonatomic) NSInteger lastPageBeforeRotate;

Then override the willRotateToInterfaceOrientation:toInterfaceOrientation:duration method and assign calculated value to it.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    int pageWidth = self.scrollView.contentSize.width / self.images.count;
    int scrolledX = self.scrollView.contentOffset.x;
    self.lastPageBeforeRotate = 0;

    if (pageWidth > 0) {
        self.lastPageBeforeRotate = scrolledX / pageWidth;
    }

    [self showBackButton:NO];
}

Then we ensure that before rotation is performed, we set our scrollview's content offset correctly, so as to focus it to our lastPageBeforeRotate

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
        if (self.lastPageBeforeRotate != -1) {
            self.scrollView.contentOffset = CGPointMake(self.scrollView.bounds.size.width * self.lastPageBeforeRotate, 0);
            self.lastPageBeforeRotate = -1;
        }
}
like image 36
Shardul Avatar answered Nov 05 '22 07:11

Shardul


Updated answer for iOS 8+

Implement viewWillTransitionToSize:withTransitionCoordinator: in your controller.

Example:

-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
    NSUInteger visiblePage = (NSInteger) self.scrollView.contentOffset.x / self.scrollView.bounds.size.width;

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
        self.scrollView.contentOffset = CGPointMake(visiblePage * self.scrollView.bounds.size.width, self.scrollView.contentOffset.y);
    } completion:nil];
}
like image 4
Valentin Solina Avatar answered Nov 05 '22 08:11

Valentin Solina