iOS8下,使用CGAffineTransform旋转UIView时,UIView未能进行调整大小。

4

我有一个UIViewController,在设备旋转时只旋转其中的一些子视图。这在iOS7下运行良好,但在iOS8下出现问题。看起来在iOS8下,UIView的边界会受到变换的影响而发生调整。这是意料之外的。

以下是一些代码:

@interface VVViewController ()
@property (weak, nonatomic) IBOutlet UIView *pinnedControls;
@property (nonatomic, strong) NSMutableArray *pinnedViews;

@end

@implementation VVViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.pinnedViews = [NSMutableArray array];
    [self.pinnedViews addObject:self.pinnedControls];
}

-(void)viewWillLayoutSubviews
{
    [super viewWillLayoutSubviews];

    [UIViewController rotatePinnedViews:self.pinnedViews forOrientation:self.interfaceOrientation];
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];

    if (UIInterfaceOrientationIsLandscape(toInterfaceOrientation) && UIInterfaceOrientationIsLandscape(self.interfaceOrientation))  {
        [UIViewController rotatePinnedViews:self.pinnedViews forOrientation:toInterfaceOrientation];
    }
}

@end

我们在UIViewController上创建了一个分类以处理此行为。以下是相关代码:
@implementation UIViewController (VVSupport)

+ (void)rotatePinnedViews:(NSArray *)views forOrientation:(UIInterfaceOrientation)orientation {
    const CGAffineTransform t1 = [UIViewController pinnedViewTansformForOrientation:orientation counter:YES];
    const CGAffineTransform t2 = [UIViewController pinnedViewTansformForOrientation:orientation counter:NO];
    [views enumerateObjectsUsingBlock:^(UIView *view, NSUInteger idx, BOOL *stop) {
        // Rotate the view controller
        view.transform = t1;
        [view.subviews enumerateObjectsUsingBlock:^(UIView *counterView, NSUInteger idx, BOOL *stop) {
            // Counter-rotate the controlsUIin the view controller
            counterView.transform = t2;
        }];
    }];
}

+ (CGAffineTransform)pinnedViewTansformForOrientation:(UIInterfaceOrientation)orientation counter:(BOOL)counter {
    CGAffineTransform t;
    switch ( orientation ) {
        case UIInterfaceOrientationPortrait:
        case UIInterfaceOrientationPortraitUpsideDown:
            t = CGAffineTransformIdentity;
            break;

        case UIInterfaceOrientationLandscapeLeft:
            t = CGAffineTransformMakeRotation(counter ? M_PI_2 : -M_PI_2);
            break;

        case UIInterfaceOrientationLandscapeRight:
            t = CGAffineTransformMakeRotation(counter ? -M_PI_2 : M_PI_2);
            break;
    }

    return t;
}

@end

这是 nib 的样子:
IBOutlet pinnedControls 对应着 nib 中被命名为 pinned 的 UIView:
在 iOS7 或 iOS8 竖屏模式下,结果如下图所示:
而在 iOS7 横屏模式下,结果如下图所示:
但是,在 iOS8 (GM) 下没有这种行为。相反,我看到的是这样的:
请注意,“Pinned Label” 文字的 UILabel 中心与未改变大小以适应旋转的 pinned UIView 底部的距离保持不变。该 UIView 的所有边沿都固定在超级视图的顶部、左侧、底部和右侧。
在 iOS8 下,它看起来似乎与 Auto Layout 互动方式不同。我有点困惑。我知道我不能依赖于 frame。我可能只会开始手动设置 bounds,但那似乎是错误的事情,实际上是绕过了 Auto Layout。

类似的问题.....orz - Calvin Chan
我在缩放转换方面遇到了同样的问题。目前还没有解决方案... - ShayDavidson
我曾经遇到过同样的问题。这是我的答案:https://dev59.com/X4fca4cB1Zd3GeqPodkE - Jan
3个回答

1

这个问题困扰了我几天,我通过更改动画块中setTransform调用的时间来解决了它。

当转到横屏时,我在设置新框架之后设置变换。当转到竖屏时,我在设置新框架之前设置变换。所有这些都在“animateWithDuration…”方法的动画块中进行。

我不确定它是否会直接帮助您解决代码问题,但它可能会激发一些灵感,因为我们肯定遇到了类似的问题。


0
在iOS8中,根据设备方向需要使用UITraitCollections来调整UIviewControllers的大小。否则,当您尝试旋转时,您会得到一个处于纵向模式的UIview,而手机却处于横向模式。因此,正确的步骤是旋转并覆盖UITraitCollections。
编辑: 我使用以下代码覆盖了我的UITraitCollection UITraitCollection *horTrait = [UITraitCollection traitCollectionWithHorizontalSizeClass:UIUserInterfaceSizeClassCompact]; UITraitCollection *verTrait = [UITraitCollection traitCollectionWithVerticalSizeClass:UIUserInterfaceSizeClassCompact]; UITraitCollection *finalTrait = [UITraitCollection traitCollectionWithTraitsFromCollections:@[horTrait,verTrait]]; [self.parentViewController setOverrideTraitCollection:finalTrait forChildViewController:self]; 不幸的是,如果我要修改的UIviewController没有parentViewController,它就无法工作。

有趣。我们的应用程序有几个iOS8视觉异常,它们还没有成为我的待办事项列表的重点,但当它们出现时,我一定会记住这一点。顺便问一下,你覆盖UITraitCollections是做什么的? - Paul Cezanne
1
我覆盖了UITraitCollections,所以当你尝试手动旋转视图时,视图会重新调整为横向形状,否则它会保持纵向形状。 - Lucas Chwe

0

这更像是一个解决方法而不是一个修复方法,因此它可能无法帮助处于类似情况的每个人。我的问题是,在应用变换后,外部“固定”视图再次被调整大小。

我的解决方案是将固定视图上的约束条件更改为垂直居中、水平居中以及宽度和高度相等的常量。

然后,在viewDidLoad中,我将固定视图的高度和宽度设置为主屏幕的高度。这使得视图成为正方形,因此我不在乎它是否多旋转了一次。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接