开发者

UIViewController orientation changes in a UINavigationController stack

I have a UINavigationController with two UIViewControllers on it (A and B). From A, I push B onto the stack. Then the user re-orients the device. I need to move some things around the screen (buttons, etc) to be visible in the new orientation on A.

I find that -shouldAutorotateToInterfaceOrientation is getting called on both A and B (and returning YES). But the -will / -didRotateFromInterfaceOrientation are only getting called on the visible ViewController (B). When B gets popped off the stack, A is shown in the new (correct) orientation but without the buttons getting moved as needed.

To solve this, I find myself implementing the following pattern:

in header file:

@interface A : UIViewController {
    // ...
    UIInterfaceOrientation layoutOrientation;
}
// ...
- (void)orientationChanged;
@end

in .m file:

- (void)viewDidLoad {
    // ...
    layoutOrientation = self.interfaceOrientation;
}

- (void)viewWillAppear:(BOOL)animated {
    // ...
    if (layoutOrientation != self.interfaceOrientation) {
        [self orientationChanged];
    }
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    [self orientationChanged];
}

- (void)orientationChanged {
    // move my buttons
    layoutOrientation = self.interfaceOrientation;
}

Essentially, I'm checking to see if the orientation changed in -viewWillAppear and doing the work to update the UI there if needed. It works just fine, but this seems (a) tedious, and (b) a lot of duplicated code among my various classes like A. I can fix (b) by moving the code to a common superclass, but this still seems like something I shouldn't have to do.

Is there a better way of moving my buttons around on views that are not top-most on the navigation st开发者_运维技巧ack? My views come from .xibs if there's something in IB I need to check. Should I just be designing my views such that they don't need to move buttons around when the orientation changes?

Thanks!


I prefer doing as much layout as possible in -layoutSubviews; there are various ways to detect orientation but I just compare bounds.size.width to bounds.size.height.

willAnimateRotationToInterfaceOrientation:duration: is more for "special" animations like sliding a view out the bottom and in from the side.

Combining this with layout in a nib is tedious. Recently, I've just mocked up the portrait UI in the nib until it works well enough and then written equivalent code to do the same thing but also support landscape.


I solved by implementing the needed-UI-changes in viewDidAppear. In my case I simply call willRotateToInterfaceOrientation.

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];

    [self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜