0

I have create an empty project that only allows landscape orientations with a storyboard containing only a UIViewController as rootViewController with a button in its center.

landscape orientation only

- (IBAction)onClick:(UIButton *)sender {
    sender.superview.transform = CGAffineTransformMakeTranslation(-320, 0);
}

The expected is that when clicking that button the view moved 320 to the left, but unfortunately what happens is that the view is rotating anti-clockwise and moving left at the same time. It seems that somehow the application thinks it is set to the portrait view and it translate the view taking that into account and this is what happens:

rotating instead moving left

I'm sure I am missing something here but I have no idea what it is.

I've tried to defined methods on the viewController such - (BOOL)shouldAutorotate and - (NSUInteger)supportedInterfaceOrientations but it didn't change this behaviour.

Any help would be appreciated.

Thanks in advance

4

2 に答える 2

2

Your app has a UIWindow, which contains your root view controller's view, which contains the button:

  • UIWindow
    • your root view
      • UIButton

What you didn't understand is that the UIWindow rotates the user interface by applying a rotation transform to your root. Take a look at the view hierarchy when the interface is in landscape-left orientation:

(lldb) po [[UIApp keyWindow] recursiveDescription]
(id) $1 = 0x0922ee80 <UIWindow: 0x942c280; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x942c380>>
   | <UIView: 0x9432b30; frame = (20 0; 748 1024); transform = [0, -1, 1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x9432be0>>
   |    | <UIRoundedRectButton: 0x942f7a0; frame = (476 352; 73 44); opaque = NO; layer = <CALayer: 0x942f8c0>>
   |    |    | <UIGroupTableViewCellBackground: 0x94300b0; frame = (0 0; 73 44); userInteractionEnabled = NO; layer = <CALayer: 0x9430180>>
   |    |    | <UIImageView: 0x9430af0; frame = (1 1; 71 43); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x9431340>>
   |    |    | <UIButtonLabel: 0x94319c0; frame = (12 12; 49 19); text = 'Button'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x9431d10>>

See how the UIWindow's subview (UIView: 0x942c380) has a transform of [0, -1, 1, 0, 0, 0]? That transform rotates your top-level view 90˚ counter-clockwise. If you rotate your device (or the simulator) to landscape-right orientation, you will see that the transform becomes [0, 1, -1, 0, 0, 0]:

(lldb) po [[UIApp keyWindow] recursiveDescription]
(id) $2 = 0x07436d90 <UIWindow: 0x942c280; frame = (0 0; 768 1024); layer = <UIWindowLayer: 0x942c380>>
   | <UIView: 0x9432b30; frame = (0 0; 748 1024); transform = [0, 1, -1, 0, 0, 0]; autoresize = W+H; layer = <CALayer: 0x9432be0>>
   |    | <UIRoundedRectButton: 0x942f7a0; frame = (476 352; 73 44); opaque = NO; layer = <CALayer: 0x942f8c0>>
   |    |    | <UIGroupTableViewCellBackground: 0x94300b0; frame = (0 0; 73 44); userInteractionEnabled = NO; layer = <CALayer: 0x9430180>>
   |    |    | <UIImageView: 0x9430af0; frame = (1 1; 71 43); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x9431340>>
   |    |    | <UIButtonLabel: 0x94319c0; frame = (12 12; 49 19); text = 'Button'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x9431d10>>

When you reset the view's transform, you're losing the rotation, so the view reverts to its “default” rotation of 0˚, which is the portrait rotation.

Adam Lockhart's answer will fix this temporarily, but if the user rotates the device, the UIWindow will reset your view's transform, losing the translation you applied.

The correct way to handle this is to not apply your own transform to your top-level view. Give your top-level view a subview that you can transform, and put your button inside that:

  • UIWindow
    • your root view
      • your transformable view
        • UIButton
于 2012-12-03T22:19:11.210 に答える
1

You need to apply the transform to its existing transform.

- (IBAction)onClick:(UIButton *)sender {
    sender.superview.transform = CGAffineTransformTranslate(sender.superview.transform, -320, 0);
}
于 2012-12-03T21:45:34.023 に答える