开发者

How to hide a UIView completely when changing orientation?

I want to design a view/view controler that automaticaly shows/hides a subview when in landscape orientation. I want the subview to dissapear completely and other subviews to take up its space.

Using a UIViewController, I wrote code that sets the subviews' frame property and call it on:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration;

This solves the problem most of the times but has problems when the orientation change is happeni开发者_高级运维ng when the view is not appearing. to bypass this, I am also calling the resizing method on:

- (void)viewWillAppear:(BOOL)animated;

but this has problems in some rare cases (involving a UISearchDisplayController) so I am also calling the resizing method on

- (void)viewDidAppear:(BOOL)animated;

As you can understand, I am unhappy with this code and I am looking for a better/more performant way to do this.

Any ideas?


Assuming all you have is a UIWebView and an ad banner, then you can just manually resize the webView when in landscape:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toOrientation 
                                duration:(NSTimeInterval)duration
{
    if (toOrientation == UIInterfaceOrientationPortrait ||
        toOrientation == UIInterfaceOrientationPortraitUpsideDown) {
            [adView setHidden:NO];
        }
    } else {
        if (toOrientation == UIInterfaceOrientationLandscapeLeft ||
            toOrientation == UIInterfaceOrientationLandscapeRight) {
            [adView setHidden:YES];
        }       
    }
}

Then also do

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromOrientation 
                                duration:(NSTimeInterval)duration
{
    UIInterfaceOrientation toOrientation = self.interfaceOrientation;
    if (toOrientation == UIInterfaceOrientationPortrait ||
        toOrientation == UIInterfaceOrientationPortraitUpsideDown) {
            [webView setBounds:CGRectMake(0.0,0.0,320.0,436.0)];
        }
    } else {
        if (toOrientation == UIInterfaceOrientationLandscapeLeft ||
            toOrientation == UIInterfaceOrientationLandscapeRight) {
            [webView setBounds:CGRectMake(0.0,0.0,480.0,320.0)];
        }       
    }
}

The dimensions assume 44.0 height for the ad banner and no nav bar (44.0) or status bar (20.0), so you may need to adjust the numbers for your layout.


Inside

- (void)didRotateFromInterfaceOrientation:
    (UIInterfaceOrientation)fromInterfaceOrientation

To hide it

sub_view.hidden = YES;

To show it again

sub_view.hidden = NO;


If there are several subviews that need to be laid out very differently in landscape and portrait, then it may be easier to hack it with an extra UIView, say landscapeView, added in the IB. Load this view up with buttons, subviews, etc and lay it out as you like. You can use all the same connections as with the usual (portrait) view. Remember to declare IBOutlet UIView *landscapeView; in the header. Then you can add the view using this:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toOrientation 
                                duration:(NSTimeInterval)duration
{
    if ([landscapeView superview]) {
        if (toOrientation == UIInterfaceOrientationPortrait ||
            toOrientation == UIInterfaceOrientationPortraitUpsideDown) {
            [landscapeView removeFromSuperview];
        }
    } else {
        if (toOrientation == UIInterfaceOrientationLandscapeLeft ||
            toOrientation == UIInterfaceOrientationLandscapeRight) {
            [[self view] addSubview:landscapeView];
        }       
    }
}

If the timing doesn't work out as you like, then you could also try something similar inside

-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation;

If you want to get even fancier, then you can leave the main view empty, create both a UIView *portraitView and a UIView *landscapeView, then remove the current view in willRotateToInterfaceOrientation and add the new view in didRotateToInterfaceOrientation.

To be safe, you should also make sure the correct view is shown initially:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    UIInterfaceOrientation toOrientation = self.interfaceOrientation;
    if (toOrientation == UIInterfaceOrientationPortrait ||
        toOrientation == UIInterfaceOrientationPortraitUpsideDown) {
        [self.view addSubview:portraitView];
    } else {
        [self.view addSubview:landscapeView];
    }

}

and also

- (void)viewWillDisappear:(BOOL)animated
{
    if ([landscapeView superview]) {
        [landscapeView removeFromSuperview];
    }
    if ([portraitView superview]) {
        [portraitView removeFromSuperview];
    }
}


an option is to present a modal view with a crossfade transition on rotate, and to dismiss it when it gets rotated back.


Personnaly, for situations like this, I feel like coding your subView's position is much simpler than relying on the framework's layout management.

So, assuming you app displays a title bar, which has a height of 20 points, here's what I would do:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    CGFloat titleBarHeight = 20;
    CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
    if(UIInterfaceOrientationIsPortrait(toInterfaceOrientation)){
        webView.frame = CGRectMake(0, 0, 320, 480 - titleBarHeight - navBarHeight - adView.frame.size.height);
        adView.hidden = NO;
    }else{
        webView.frame = CGRectMake(0, 0, 480, 320 - titleBarHeight - navBarHeight);
        adView.hidden = YES;
    }
}


I take advantage of the parent view's bounds in my code. Try the code below see if the animation works well for you.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    switch (toInterfaceOrientation) {
        case UIInterfaceOrientationLandscapeLeft:
        case UIInterfaceOrientationLandscapeRight:
        {
            webView.frame = self.view.bounds;
        adView.hidden=YES;
            break;
        }
    }
}


- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];

    switch (fromInterfaceOrientation) {
        case UIInterfaceOrientationLandscapeLeft:
        case UIInterfaceOrientationLandscapeRight:
        {
            webView.frame = originalFrame;
            adView.hidden=NO;
            break;
        }
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
    webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    adView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    originalFrame = webView.frame;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    return YES;
}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜