Overriding layoutSubviews when rotating UIView

2019-05-10 17:10发布

When rotating a scroll view inside a UIView, the scroll view doesnt position correctly using its default autoresizing behaviour.

Thus, when rotation occurs, in willRotateToInterfaceOrientation i call [self.view setNeedsLayout]; and my layoutSubviews method is as follows:

- (void)layoutSubviews {
    NSLog(@"here in layoutSubviews");
}

But putting a breakpoint on the method, and it never seems to enter the method.

Do i need to do something else to get it to work?

Thanks.

5条回答
男人必须洒脱
2楼-- · 2019-05-10 17:23

You should override willAnimate... and set the new frame of your view. Layoutsubviews should be called automatically during rotation.

查看更多
劳资没心,怎么记你
3楼-- · 2019-05-10 17:25

Calling [someScrollView setNeedsLayout] may not actually do anything if the view hasn't been resized or moved. As you say, that method is never called using the default autoresizing behavior, because the default behavior is to not resize at all. You most likely need to set someScrollView.autoresizingMask. When the interface rotates, the view will resize itself, and layoutSubviews will get called.

查看更多
Bombasti
4楼-- · 2019-05-10 17:26

willRotateToInterfaceOrientation is being called before the orientation is changed, hence your UIView will still have the old size. Try using didRotateFromInterfaceOrientation instead.

Also, for added effect, I would hide the scrollView ( maybe with inside an UIAnimation block) in willRotateToInterfaceOrientation, resize it and then show it in didRotateFromInterfaceOrientation (again, maybe inside an animation block).

Here is a snippet from one of my apps:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3f];
self.myScroll.hidden = YES;
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView commitAnimations];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3f];
self.myScroll.hidden = NO;
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView commitAnimations];
}

You can even do fancy stuff by checking the new orientation using UIInterfaceOrientationIsPortrait(orientation) or UIInterfaceOrientationIsLandscape(orientation).

查看更多
贪生不怕死
5楼-- · 2019-05-10 17:42

The method doesn't get called because a ViewController doesn't have a layoutSubviews method.

When you call [self.view setNeedsLayout]; it will just call the layoutSubviews method of the view of the view controller: [self.view layoutSubviews].

You will need to subclass the UIScrollview to make this work.

查看更多
The star\"
6楼-- · 2019-05-10 17:46

Actually, you probably want to override the view controller willAnimateRotationToInterfaceOrientation:duration: method (cut from an example of mine):

-(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 
                                        duration:(NSTimeInterval)duration {
    if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
        boardView.frame = CGRectMake(0, 0, 320, 320);
        buttonsView.frame = CGRectMake(0, 320, 320, 140);
    } else {
        boardView.frame = CGRectMake(0, 0, 300, 300);
        buttonsView.frame = CGRectMake(300, 0, 180, 300);        
    }

}

查看更多
登录 后发表回答