1

我的应用程序使用 CMMotionManager 来跟踪设备运动,但 iOS 始终以标准设备方向(底部的主页按钮)返回设备运动数据。

为了让运动数据与我的 UIView 具有相同的方向,我将视图变换从我的视图向下累积到窗口,如下所示:

CGAffineTransform transform = self.view.transform;
for (UIView *superview = self.view.superview; superview; superview = superview.superview) {
    CGAffineTransform superviewTransform = superview.transform;
    transform = CGAffineTransformConcat(transform, superviewTransform);
}

此变换在 iOS 6 和 7 下正确计算,但 iOS 8 更改了旋转模型,现在无论设备如何定向,视图始终返回标识变换(无旋转)。尽管如此,来自运动管理器的数据仍然固定在标准方向。

监视 UIDevice 旋转通知并手动计算四个变换似乎是在 iOS 8 下获取此变换的一种方法,但它也似乎很糟糕,因为设备方向不一定与我的视图方向匹配(即,iPhone 上的上行是设备方向不是通常支持)。

在 iOS 8 下,将 CMMotionManager 的输出转换为特定 UIView 的方向的最佳方法是什么?

4

2 回答 2

1

虽然不是很明显,但在 iOS 8 及更高版本中推荐的方法是使用转换协调器。

viewWillTransition(to:with:)中,协调器可以向您传递一个对象,该对象UIViewControllerTransitionCoordinatorContext在您调用的任何方法的完成块中采用(UIKit 使用的默认协调器实际上是它自己的上下文,但不一定是这种情况)。

上下文的targetTransform属性是动画结束时应用到界面的旋转。请注意,这是一个相对变换,而不是产生的界面绝对变换。

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    let animation: (UIViewControllerTransitionCoordinatorContext) -> Void = { context in
        // Update animatable properties.
    }

    coordinator.animate(alongsideTransition: animation) { context in
        // Store or use the transform.
        self.mostRecentTransform = context.targetTransform
    }
}

虽然旧方法仍然有效,但当您需要协调动画过渡时,例如使用图形框架或使用自定义布局时,此 API 会更加灵活。

于 2016-07-21T18:52:30.780 回答
0

我找不到直接计算转换的方法,因此我更改了代码以在我的视图控制器中收到 willRotateToInterfaceOrientation: 消息时手动计算设置转换,如下所示:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    CGAffineTransform transform;
    switch (toInterfaceOrientation) {
        case UIInterfaceOrientationLandscapeLeft:
            transform = CGAffineTransformMake(
                0, -1,
                1, 0,
                0, 0);
            break;

        case UIInterfaceOrientationLandscapeRight:
            transform = CGAffineTransformMake(
                0, 1,
                -1, 0,
                0, 0);
            break;

        case UIInterfaceOrientationPortraitUpsideDown:
            transform = CGAffineTransformMake(
                -1, 0,
                0, -1,
                0, 0);
            break;

        case UIInterfaceOrientationPortrait:
            transform = CGAffineTransformIdentity;
            break;
    }
    self.motionTransform = transform;
}
于 2014-09-06T01:23:03.900 回答