1

I rotated a view using CGAffineTransformMakeRotation. ( iPhone - allow landscape orientation on just one viewcontroller )

As you can see below, the images have white region in left and right.
I want the image take up the whole space with black background.(at least in one dimension, width or height )

enter image description here

Below is the full code

- (void) viewDidLoad
{
    [super viewDidLoad];

    self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    self.view.backgroundColor = [UIColor blackColor];

    self.imageView.backgroundColor = [UIColor blackColor];
    self.imageView.opaque = NO;
    self.imageView.contentMode = UIViewContentModeScaleAspectFit;
    self.imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth |
        UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;

    [self.imageView setImageWithURL:[NSURL URLWithString:self.jsonAlbumImage.url_image
                                           relativeToURL: [NSURL URLWithString:@URL_BASE]]
                   placeholderImage: [GlobalHelper placeHolderImage]];

    [self.view addSubview: self.imageView];

}

- (void)didRotate:(NSNotification *)notification {
    UIDeviceOrientation orientation = [[notification object] orientation];

    if (orientation == UIDeviceOrientationLandscapeLeft) {
        [self.view setTransform:CGAffineTransformMakeRotation(M_PI / 2.0)];
    } else if (orientation == UIDeviceOrientationLandscapeRight) {
        [self.view setTransform:CGAffineTransformMakeRotation(M_PI / -2.0)];
    } else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
        [self.view setTransform:CGAffineTransformMakeRotation(M_PI)];
    } else if (orientation == UIDeviceOrientationPortrait) {
        [self.view setTransform:CGAffineTransformMakeRotation(0.0)];
    }
}

-- EDIT --

What worked for me in the end .. don't know why modification does work.. any explanation would be great!

  UIDeviceOrientation orientation = [[notification object] orientation];

    CGAffineTransform t;
    CGRect rect;
    if (orientation == UIDeviceOrientationLandscapeLeft) {
        t = CGAffineTransformMakeRotation(M_PI / 2.0);
        rect = CGRectMake(0,0,480,320);
    } else if (orientation == UIDeviceOrientationLandscapeRight) {
        t = CGAffineTransformMakeRotation(M_PI / -2.0);
        rect = CGRectMake(0,0,480,320);
    } else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
        t = CGAffineTransformMakeRotation(M_PI);
        rect = CGRectMake(0,0,320,480);
    } else if (orientation == UIDeviceOrientationPortrait) {
        t = CGAffineTransformMakeRotation(0.0);
        rect = CGRectMake(0,0,320,480);
    }
    else
        return; // looks like there are other orientations than the specified 4

    [self.view setTransform:t];
    self.view.bounds = rect;
Community
  • 1
  • 1
eugene
  • 39,839
  • 68
  • 255
  • 489
  • it looks like it is taking up the whole view in height. If the view is taller than it is wide, this would be the desired behavior. – Chris Truman Jan 15 '13 at 08:27
  • no there's black background which is not taken up by image on both top and bottom – eugene Jan 15 '13 at 08:34
  • have you given the proper content mode for the imageview – pradeepa Jan 15 '13 at 08:44
  • log the bounds of controller's view and image view and check – pradeepa Jan 15 '13 at 08:48
  • they are both (320,480) even when rotated. Yes I tried setting 480,320 to view.frame imageView.frame, but did not fix the issue.. maybe I shouldn't set origin of the frame? .. brb – eugene Jan 15 '13 at 08:52
  • Doesn't work.. if (orientation == UIDeviceOrientationLandscapeRight || orientation == UIDeviceOrientationLandscapeLeft) { CGRect screenRect = [[UIScreen mainScreen] bounds]; CGRect temp = self.view.frame; temp.size.width = screenRect.size.height; temp.size.height = screenRect.size.width; self.view.frame = temp; } – eugene Jan 15 '13 at 08:56

1 Answers1

1

In - (void)didRotate:(NSNotification *)notification, you need to relayout your views so that they occupy all the space available. You could do something like this:

- (void)didRotate:(NSNotification *)notification {
  UIDeviceOrientation orientation = [[notification object] orientation];

  CGAffineTransform t;
  if (orientation == UIDeviceOrientationLandscapeLeft) {
    t = CGAffineTransformMakeRotation(M_PI / 2.0);
  } else if (orientation == UIDeviceOrientationLandscapeRight) {
    t = CGAffineTransformMakeRotation(M_PI / -2.0);
  } else if (orientation == UIDeviceOrientationPortraitUpsideDown) {
    t = CGAffineTransformMakeRotation(M_PI);
  } else if (orientation == UIDeviceOrientationPortrait) {
    t = CGAffineTransformMakeRotation(0.0);
  }

  CGPoint screenCenter = CGPointMake([UIScreen mainScreen].bounds.width/2,[UIScreen mainScreen].bounds.height/2);
  self.view.center = CGPointApplyAffineTransform(screenCenter, t);
  self.view.bounds = CGRectApplyAffineTransform([UIScreen mainScreen].bounds, t);
  [self.view setTransform:t];

}

Where :

CGRectApplyAffineTransform

Applies an affine transform to a rectangle.

       CGRect CGRectApplyAffineTransform (
           CGRect rect,
           CGAffineTransform t
         );

Try also removing this line:

self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;

You don´t need it if you are not going to use autorotation and I fear it might conflict with your own setting the view's frame. This is just an hypothesis to account for the fact that you are not seeing the view´s frame change.

EDIT:

I'd very much like to know what this transform thing does

well, the transform is doing the rotation.

rotating is relative to an anchor point which is used as a pivot; what happens is that if the anchor point is not in the middle of the view being rotated, then the view is also translated (imagine a rotation around a vertex).

So, it is correct to set the bounds to make things even; indeed I was suggesting just that with the lines:

  self.view.center = CGPointApplyAffineTransform(screenCenter, t);
  self.view.bounds = CGRectApplyAffineTransform([UIScreen mainScreen].bounds, t);

but possibly the idea of applying the same transform to both the center and the bounds was not blessed. (that is also why I asked for some traces, to see what was happening :-)

sergio
  • 68,819
  • 11
  • 102
  • 123
  • CGRectApplyCGAffineTransform's return value is int.. Would you mind explaining why removing the autoresizingMask can help the situation? – eugene Jan 15 '13 at 09:17
  • Sorry, the correct spelling was `CGRectApplyAffineTransform`. See my edited answer for more details. – sergio Jan 15 '13 at 10:31
  • tried it, and doesn't work.. image dissappears in other rotations than portrait. I logged view/imageView's bounds, and it is (480,320) – eugene Jan 16 '13 at 05:52
  • that´s good for a start. what about setting the view center like I suggest in my edited answer? – sergio Jan 16 '13 at 10:02
  • got little better, if I rotate to vertical(becomes all white), then come back to portrait, image is there.. – eugene Jan 22 '13 at 12:05
  • some NSLog here and there would help understanding what is happening, really... :-) – sergio Jan 22 '13 at 12:42
  • Thank you for help! I'd very much like to know what this transform thing does.. but.. in the mean time, I did set rect = cgrectmake(0,0,480,320) on landscape (320,480) on portrait.. `[self.view setTransform:t]; self.view.bounds = rect;` and it works fine.(after the main if-else block of code), i'll post the code in the question. – eugene Jan 22 '13 at 12:59
  • I think what you do is perfectly fine. See my edit for more clarifications. – sergio Jan 22 '13 at 13:11