Swap problems with UIScrollView swap

I am having problems using UIScrollView on IPhone while working with rotation. I used the Apple PageControl example as a model, but I create a scrollview myself in the view.

1) Scrollview works, as expected, when loading the default "Portrait", scrolling left and right horizontally

2) Out of the box, when the CW rotation and reinitialization basically turn it on its side, and now it turns vertically down, rather than horizontal. It seems that the width / height of the scroll frame does not change, but the orientation itself.

3) I tried to add some orientation detection logic to correctly sort and scroll the page depending on the orientation, which doesn’t work correctly, but only if I rotate the CCW into the landscape. If I go to CW, it starts on the right and scrolls left, and everything doesn't work.

Obviously, this is becoming hacky, so there is the right way to configure my UIScrollview and reinitialize it with rotations so that it always scrolls left and right?


- (void)loadView {
    [self setupPage];
}

-(void) setupPage {
  // lazy init view controllers
  NSMutableArray *controllers = [[NSMutableArray alloc] init];
    for (unsigned i = 0; i = kNumberOfPages) return;

    // replace the placeholder if necessary
    MyViewController *controller = [viewControllers objectAtIndex:page];
    if ((NSNull *)controller == [NSNull null]) {
        controller = [[MyViewController alloc] initWithPageNumber:page];
        [viewControllers replaceObjectAtIndex:page withObject:controller];
        [controller release];
    }

    // add the controller view to the scroll view
    if (nil == controller.view.superview) {
        CGRect frame = scrollView.frame;

        int x = 0;
        int y = 0;
        UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
        if(orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight){
            x = 0;
            y = frame.size.height * page; 
        } else {
            x = frame.size.width * page;
            y = 0;
        }

        frame.origin.x = x;
        frame.origin.y = y;
        controller.view.frame = frame;
        [scrollView addSubview:controller.view];
    }
}

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    // We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
    // which a scroll event generated from the user hitting the page control triggers updates from
    // the delegate method. We use a boolean to disable the delegate logic when the page control is used.
    if (pageControlUsed) {
        // do nothing - the scroll was initiated from the page control, not the user dragging
        return;
    }

    // Switch the indicator when more than 50% of the previous/next page is visible
    CGFloat pageWidth = scrollView.frame.size.width;
    int offset = 0;
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
    if(orientation == UIDeviceOrientationLandscapeLeft || orientation == UIDeviceOrientationLandscapeRight){
        pageWidth = scrollView.frame.size.height;
        offset = scrollView.contentOffset.y; 
    } else {
        pageWidth = scrollView.frame.size.width;
        offset = scrollView.contentOffset.x ;
    }

    //CGFloat pageWidth = scrollView.frame.size.width;
    int page = floor((offset - pageWidth / 2) / pageWidth) + 1;
    pageControl.currentPage = page;

    // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
    [self loadScrollViewWithPage:page - 1];
    [self loadScrollViewWithPage:page];
    [self loadScrollViewWithPage:page + 1];

    // A possible optimization would be to unload the views+controllers which are no longer visible
}

// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    pageControlUsed = NO;
}

// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    pageControlUsed = NO;
}


- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
{
    [self setupPage];
}

+3
source share
1 answer

You do not change the contentSize of your scrollview, so when it rotates, it does not know that it is wider than the higher.

In addition, as a shortcut, each VC has an interfaceOrientation property already set, and there are built-in functions for determining the orientation: UIInterfaceOrientationIsPortrait (self.interfaceOrientation) and UIInterfaceOrientationIsLandscape (self.interfaceOrientation).

, , willRotateToInterfaceOrientation: , , .

+2

Source: https://habr.com/ru/post/1762159/


All Articles