CGAffineTransform Make Translation 导致 iOS 6 上的视图旋转

Posted

技术标签:

【中文标题】CGAffineTransform Make Translation 导致 iOS 6 上的视图旋转【英文标题】:CGAffineTransformMakeTranslation causing view rotation on iOS6 【发布时间】:2012-12-03 16:15:03 【问题描述】:

我创建了一个空项目,它只允许横向,情节提要仅包含一个 UIViewController 作为 rootViewController,其中心有一个按钮。

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

预期的是,当单击该按钮时,视图向左移动了 320,但不幸的是,视图在逆时针旋转的同时向左移动。似乎应用程序以某种方式认为它被设置为纵向视图,并在考虑到这一点的情况下翻译视图,这就是发生的事情:

我确定我在这里遗漏了一些东西,但我不知道它是什么。

我尝试在 viewController 上定义方法,例如 - (BOOL)shouldAutorotate- (NSUInteger)supportedInterfaceOrientations,但并没有改变这种行为。

任何帮助将不胜感激。

提前致谢

【问题讨论】:

【参考方案1】:

您的应用有一个UIWindow,其中包含您的根视图控制器的视图,其中包含按钮:

UIWindow 您的根视图 UIButton

您不明白的是UIWindow 通过对您的根应用旋转变换来旋转用户界面。当界面处于横向左方向时,查看视图层次结构:

(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>>

查看UIWindow 的子视图(UIView: 0x942c380)如何转换为[0, -1, 1, 0, 0, 0]?该变换将您的***视图逆时针旋转 90˚。如果你将你的设备(或模拟器)旋转到横向,你会看到变换变成[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>>

当您重置视图的变换时,您会失去旋转,因此视图会恢复到其“默认”旋转 0˚,即纵向旋转。

Adam Lockhart 的回答将暂时解决此问题,但如果用户旋转设备,UIWindow 将重置您的视图转换,丢失您应用的翻译。

处理此问题的正确方法是将您自己的转换应用到您的***视图。为您的***视图提供一个可以转换的子视图,并将您的按钮放在其中:

UIWindow 您的根视图 您的可变形视图 UIButton

【讨论】:

这是不正确的。应用于窗口的转换不会撤消其中的视图和子视图的任何转换。它只会将转换应用于窗口。 @AdamLockhart 我没有谈到对窗口应用变换,zanona 的代码也没有对窗口应用变换。我谈到了将变换应用于窗口的子视图,这是 zanona 的代码所做的。我测试了我的解决方案,也测试了你的解决方案。如果界面旋转到另一个方向,你的翻译会丢失。 您写道“UIWindow 将重置您的视图转换,丢失您应用的翻译”。这是不可信的。我也测试过这个。我有软件,其中一切的定位都依赖于应用转换。如果这些转换在用户旋转设备时丢失,那将是荒谬的。 @AdamLockhart 当您引用我时,您忽略了“如果用户旋转设备”。我在我的答案中添加了另一个视图层次结构打印输出。查看UIView: 0x942c380 上的转换。看看它如何从第一个打印输出(横向左方向)变为第二个打印输出(横向右方向)?系统更改了变换,因为我将模拟器旋转了 180°。 对。因此,您所说的只是他不应该将变换应用于最外层视图。同意!那太荒谬了。【参考方案2】:

您需要将转换应用到其现有转换。

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

【讨论】:

以上是关于CGAffineTransform Make Translation 导致 iOS 6 上的视图旋转的主要内容,如果未能解决你的问题,请参考以下文章

使用 CGAffineTransform 的 UIView 旋转

CGAffineTransform

CGAffineTransform 操作顺序不一致

CGAffineTransform 在其他视图上

iOS形变之CGAffineTransform

仿射变换(CGAffineTransform)使用小结