排除UIView在自动旋转时的动画效果

5

简述

需要保持自动旋转,但在方向改变时排除一个UIView的自动旋转,如何实现?

背景

我需要在伴随自动旋转的动画中保持一个UIView的静止(即控件在其原地旋转),类似于iOS相机应用程序处理旋转的方式。

尝试过的方法

  • shouldAutorotate()返回false,订阅UIDeviceOrientationDidChangeNotification,并尝试为每个视图单独手动处理旋转事件。

    如果您不需要更改任何UIView的位置,则效果很好,否则在确定它应该停留在哪里以及如何将其放置在那里方面会很麻烦

  • 在主UIWindow下放置一个不旋转的UIWindow,并将主UIWindow的背景颜色设置为透明。

    如果只有一个项目,则此方法效果很好,但我不想管理一堆UIWindows

  • 反向旋转,即将UIView旋转到相反的方向。 不可靠,看起来奇怪,也会引起眩晕

  • viewWillTransitionToSize方法中覆盖动画。 失败了

  • 还有一堆其他难以在此列出的事情,但它们都失败了

问题

这个可以做到吗?如果可以,怎么做呢?

我支持iOS8及以上版本


更新 根据@Casey的示例,这是视图应该如何布局/方向:

enter image description here


1
那么,如何钩入 orientationDidChangeNotificationReceived: 通知并将 UIView 旋转到相反的方向,以有效地抵消设备的旋转呢? - Michael
那明显有点卡顿,视图会抖动。我也尝试过了(现在会更新答案)。不过是个好建议。 - MrHaze
1
我能想到的唯一建议是尝试使用UIContainerViewController,其中一个包含的视图控制器包含你不想旋转的视图。然后,该视图控制器将返回false以获取shouldAutorotate()。我不知道它是否有效,并且仍然听起来有点“靠不住”。 - Michael
这个(https://dev59.com/72s05IYBdhLWcg3wQvke)建议添加一个ViewController作为子视图来实现,但是有一条评论说它在iOS 8之后不起作用。 - Michael
我也尝试过了,评论是正确的。这也是另一个在iOS 8以下版本上运行的示例 https://gist.github.com/ffraenz/5945301 我没有尝试过,但我相信评论。 - MrHaze
3个回答

2

0

如果您想要与相机应用程序具有相同的效果,请使用大小类(请参见这里这里)。

如果不是,那么创建一个包含不旋转的视图控制器的UIWindow有什么问题呢?以下代码对我来说似乎有效(其中UILabel代表您不想旋转的视图)。

class ViewController: UIViewController {
    var staticWindow: UIWindow!

    override func viewDidLoad() {
        super.viewDidLoad()
        showWindow()
    }

    func showWindow() {
        let frame = CGRect(x: 10, y: 10, width: 100, height: 100)
        let vc = MyViewController()
        let label = UILabel(frame: frame)
        label.text = "Hi there"
        vc.view.addSubview(label)
        staticWindow = UIWindow(frame: frame)
        staticWindow.rootViewController = MyViewController()
        staticWindow.windowLevel = UIWindowLevelAlert + 1;
        staticWindow.makeKeyAndVisible()
        staticWindow.rootViewController?.presentViewController(vc, animated: false, completion: nil)
    }
}

class MyViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }

    override func shouldAutomaticallyForwardRotationMethods() -> Bool {
        return false
    }

    override func shouldAutomaticallyForwardAppearanceMethods() -> Bool {
        return false
    }

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
}

很好的回答,但是我提到过我已经尝试过了,问题在于你需要为不同的屏幕维护一堆UIWindows。 - MrHaze
你是说有一个 UIView 不应该被旋转,但它在多个视图控制器中出现了吗?它是标志还是其他什么?实际使用场景是什么? - Michael
这是一堆视图,标志只是其中之一,但不是唯一的。简单地说,有一个视频层和一堆控件在其上。该层应在整个流程中保持不变,只有部分控件会在原地旋转。我之前提过的一个例子是iOS上的相机应用程序,只有一些视图会旋转,其他视图则正常运行。 - MrHaze
尽管相机应用程序中的所有视图都在原地旋转,但只有文字没有重新定位。如果今天重写它,我想他们会使用大小类,而当时他们还没有这个功能。 - Michael

0

我认为这个问题难以回答的部分原因是因为在实践中它并没有太多意义。

假设我创建了一个视图,使用自动布局,在纵向和横向时看起来像这样:

standard layout

如果您想要防止c像您所要求的那样旋转,您期望最终的视图会是什么样子?它会是以下三个选项中的哪一个?

wonky layout

如果没有你想要实现的横向或纵向视图的图形以及动画的描述,回答你的问题将会非常困难。

你是使用NSLayoutConstraint、故事板还是基于框架的数学方法来布局你的视图?任何你可以提供的代码也将非常有帮助。


https://gist.github.com/justAnotherDev/51917652d9f18e533535 是用于生成示例视图的代码。 - Casey
如果你这样说的话可能没有意义,但有些情况下你想要应用我试图实现的功能。例如,有些视图通常会旋转,并且它们构成了背景,而你想要保持前景中的项目静态并旋转而不是移动。一个例子就是iOS相机应用程序,如果你旋转设备,控件会保持在原地,并旋转而不是移动。 - MrHaze
你太小题大做了——OP需要的不是你提供的任何选项。相反,OP想要这个:http://imgur.com/a/Dk7hO。请注意,子视图 A 和 B 已经按预期自动旋转,但是子视图 C 没有——它相对于主页按钮具有完全相同的方向,使用物理显示器上完全相同的像素(除了现在被遮挡的像素)。你的示例也很晦涩,因为除非子视图 C 充满整个屏幕,否则根本没有用例。 - Slipp D. Thompson

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