Search code examples
iphoneuiimageviewcgaffinetransform

Rotating an image 90 degrees on same position when orientation changes


Ended up with doing this: Easiest way to support multiple orientations? How do I load a custom NIB when the application is in Landscape? Works superb!

I have made an image in Photoshop which I want to use as background for my info-screen in my iPad application. The image contains text and some icons also. Around the image I have a border which is green.

The effect I am trying to achieve is:

When the user goes from the portrait orientation to landscape orientation I want the image (just the frame and the icons) to rotate 90 degrees so the image appear in landscape mode, instead of having a portrait view of the frame in landscape. The text and icons are decoupled (different layers which I have organized in different UIImageView's)they shall rotate 90 degrees.

What I have done already is the following:

Experimented a bit with this method:

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

and tried to do this:

self.btnFacebook.transform = CGAffineTransformMakeRotation(1.5707964);

which I think will rotate the btnFacebook property 90 degrees to the right (correct me if I am wrong) since it specifies positive radians. I can't seem to get it to work correctly though. Should'nt this rotate the button 90 degrees around its center coordinate in the frame? That wouldn't cause a change in the position of the button (the button is square)?

EDIT

Made an image:

enter image description here

As the image shows the image background (some custom graphics on it which looks good in both orientations) goes from portrait to landscape and rotates so it does not appear as portrait in landscape, the icons are decoupled from the background so they need to rotate as well because they need to be in the right orientation (it is social icons). The text however are on the same position, it only rotates 90 degrees without repositioning.


Solution

  • I understand your question as that you are trying to not to rotate the interface as whole but to rotate the purple and red squares individually.

    I created a UIViewController that resembles your layout.

    Interface Bulder screenshot

    The black square is a UIView and the white square is there only so that I can tell when the black view rotates. This view is wired to view1 property on the controller.

    There are 4 buttons that are wired to btnx (x runs 1 through 4) properties.

    Since I no longer want to auto rotate the interface I only support the portrait orientation.

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        // Return YES for supported orientations
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
    

    To do the rotation manually, I added a method to the ViewController. It determines the angle it needs to rotate the components from portrait to current orientation, creates a rotation transform and applies it to all outlets.

    - (void)deviceDidRotate:(NSNotification *)notification
    {
        UIDeviceOrientation currentOrientation = [[UIDevice currentDevice] orientation];
        double rotation = 0;
        UIInterfaceOrientation statusBarOrientation;
        switch (currentOrientation) {
            case UIDeviceOrientationFaceDown:
            case UIDeviceOrientationFaceUp:
            case UIDeviceOrientationUnknown:
                return;
            case UIDeviceOrientationPortrait:
                rotation = 0;
                statusBarOrientation = UIInterfaceOrientationPortrait;
                break;
            case UIDeviceOrientationPortraitUpsideDown:   
                rotation = -M_PI;
                statusBarOrientation = UIInterfaceOrientationPortraitUpsideDown;
                break;     
            case UIDeviceOrientationLandscapeLeft:     
                rotation = M_PI_2;   
                statusBarOrientation = UIInterfaceOrientationLandscapeRight;
                break;  
            case UIDeviceOrientationLandscapeRight:    
                rotation = -M_PI_2;
                statusBarOrientation = UIInterfaceOrientationLandscapeLeft;
                break;
        }
        CGAffineTransform transform = CGAffineTransformMakeRotation(rotation);
        [UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
            [self.btn1 setTransform:transform];
            [self.btn2 setTransform:transform];
            [self.btn3 setTransform:transform];
            [self.btn4 setTransform:transform];
            [self.view1 setTransform:transform];
            [[UIApplication sharedApplication] setStatusBarOrientation:statusBarOrientation];
        } completion:nil];
    }
    

    The last thing to do is to get the OS to call my method. To achieve that I added the following code to application:didFinishLaunchingWithOptions: in the AppDelegate.

    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self.viewController selector:@selector(deviceDidRotate:) name:UIDeviceOrientationDidChangeNotification object:nil];
    

    I am not sure whether this is exactly what you wanted but I believe it is at least similar so you can get some ideas from it how to solve your problem. I can provide source code for a working iPad application that I created to illustrate this.