4
votes

I have an UIView that contains a UIImageView. The UIImageViews works like the branding logo of the app. When I rotate the device, the containing UIView resizes itself to correspond to the landscape or portrait proportions of the screen.

What I'm trying to achieve is to have the UIImageView scaled accordingly, keeping proportions also on the left margin.

This is the actual code for the top white "banner":

UIView *topBanner = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, height_topBanner)];
[topBanner setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin)];
[topBanner setBackgroundColor:[UIColor whiteColor]];
topBanner.autoresizesSubviews = YES;

    // the logo
    UIImage *topBanner_logo = [UIImage imageNamed:@"logo.png"];
    float logoAspectRatio = topBanner_logo.size.width/topBanner_logo.size.height;
    topBanner_logoView = [[UIImageView alloc] initWithFrame:CGRectMake(topBanner.frame.size.width/100*3, topBanner.frame.size.height/100*7, (topBanner.frame.size.height/100*86)*logoAspectRatio, topBanner.frame.size.height/100*86)];
    [topBanner_logoView setImage:topBanner_logo];
    topBanner_logoView.backgroundColor = [UIColor blueColor];
    topBanner_logoView.contentMode = UIViewContentModeScaleAspectFit;
    [topBanner_logoView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleRightMargin)];
    [topBanner addSubview:topBanner_logoView];

[self.view addSubview:topBanner];

This is my starting point: portrait iPad on startup:

Startup in portrait mode

This is what happens when I rotate it in landscape: Landscape mode after the startup

As you can see, the proportions of the UIImage are ok, but I'm getting extra borders (I set the background color of the UIImageView to highlight it) because the UIImageView stretches itself to follow the change of the size of its container, and the UIImage is fit into the UIImageView and put on its center.

The same - reversed - happens when I start the app directly in landscape mode: Startup in landscape mode

Then I rotate it:

portrait mode after startup

... and I get the logo with extra borders on top and bottom.

I do see that I can write a function to recalculate every size on each rotation change, but I'm asking to myself if is there a way to set the UIImageView and the UIImage to make it works without hacking the autorotate/resize procedures of iOS. It sounds so simple!

3

3 Answers

1
votes

You can solve this by not using UIViewContentModeScaleAspectFit, and instead calculating the aspect ratio of the image and using that to explicitly the width or height based on the other (width or height).

e.g. I rotate to landscape, and so I want the height to be 80% of the view.

    CGFloat w = logo.image.size.width;
    CGFloat h = logo.image.size.height;
    CGFloat a = w / h;

    CGFloat h_use = self.view.height *0.8;
    CGFloat w_use = h_use*a;

Furthermore, set the content mode to UIViewContentModeScaleAspectFill instead now that you've explicitly set the aspect ratio.

0
votes

You have set the auto resizing mask to flexible height and width:

[topBanner_logoView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleRightMargin)];

If you do not do that, the default is that the view will not chance size, and therefore, the image will not either.

0
votes

I think it is because of topBanner_logoView.contentMode = UIViewContentModeScaleAspectFit;

Try topBanner_logoView.contentMode = UIViewContentModeCenter or topBanner_logoView.contentMode = UIViewContentModeLeft to prevent the UIImageView's image from resizing (and getting padding).

If the UIImageView is resizing, remove the autoresizing mask.