gpt4 book ai didi

ios - 强制 iOS View 不旋转,同时仍允许 subview 旋转

转载 作者:搜寻专家 更新时间:2023-10-30 21:49:14 24 4
gpt4 key购买 nike

我有一个带有 subview Controller 的 View Controller 。

tab bar controller
|
|
nav controller
|
|
UIPageViewController (should rotate)
|
|
A (Video Player) (shouldn't rotate)
|
|
B (Controls overlay) (should rotate)

应强制 A 始终保持纵向,但应允许 B 自由旋转。

我知道 shouldAutorotate 适用于任何 View Controller 及其 subview ,但是有什么办法可以解决这个问题吗?似乎我可以使用 shouldAutorotateToInterfaceOrientation,但这在 iOS 8 中被阻止了。

我想让视频播放器保持静止(因此无论设备方向如何,水平视频始终是水平的),同时允许控件层 subview 覆盖自由旋转。

我正在使用 Swift。

最佳答案

我遇到了这个确切的问题,并且很快发现有很多关于自动旋转的糟糕建议,特别是因为 iOS 8 处理它的方式与以前的版本不同。

首先,您不想手动应用反向旋转或订阅UIDevice 方向更改。进行反向旋转仍会导致动画效果不佳,并且设备 方向并不总是与界面 方向相同。理想情况下,您希望相机预览保持真正的静止状态,并且您的应用 UI 可以随着状态栏的方向和大小的变化而匹配,就像 native 相机应用一样。

在 iOS 8 中的方向更改期间,窗口本身而不是它包含的 View 会旋转。您可以将多个 View Controller 的 View 添加到单个 UIWindow,但只有 rootViewController 有机会通过 shouldAutorotate() 进行响应。即使您在 View Controller 级别做出旋转决定,实际上旋转的是父窗口,因此旋转了它的所有 subview (包括来自其他 View Controller 的 subview )。

解决方案是将两个 UIWindow 堆叠在一起,每个旋转(或不旋转)都有自己的 Root View Controller 。大多数应用只有一个,但您没有理由不能拥有两个并像任何其他 UIView 子类一样覆盖它们。

这是一个有效的概念验证,which I've also put on GitHub here .你的特殊情况有点复杂,因为你有一堆包含 View Controller ,但基本思想是一样的。我将在下面谈及一些具体要点。

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var cameraWindow: UIWindow!
var interfaceWindow: UIWindow!

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject : AnyObject]?) -> Bool {
let screenBounds = UIScreen.mainScreen().bounds
let inset: CGFloat = fabs(screenBounds.width - screenBounds.height)

cameraWindow = UIWindow(frame: screenBounds)
cameraWindow.rootViewController = CameraViewController()
cameraWindow.backgroundColor = UIColor.blackColor()
cameraWindow.hidden = false

interfaceWindow = UIWindow(frame: CGRectInset(screenBounds, -inset, -inset))
interfaceWindow.rootViewController = InterfaceViewController()
interfaceWindow.backgroundColor = UIColor.clearColor()
interfaceWindow.opaque = false
interfaceWindow.makeKeyAndVisible()

return true
}
}

interfaceWindow 上设置负插图,使其略大于屏幕边界,有效地隐藏了您原本会看到的黑色矩形 mask 。通常您不会注意到,因为 mask 随窗口一起旋转,但由于相机窗口是固定的,因此在旋转过程中 mask 会在角落可见。

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

这里正是您所期望的,只需为 AVCapturePreviewLayer 添加您自己的设置。

class InterfaceViewController: UIViewController {
var contentView: UIView!

override func viewDidLoad() {
super.viewDidLoad()

contentView = UIView(frame: CGRectZero)
contentView.backgroundColor = UIColor.clearColor()
contentView.opaque = false

view.backgroundColor = UIColor.clearColor()
view.opaque = false
view.addSubview(contentView)
}

override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()

let screenBounds = UIScreen.mainScreen().bounds
let offset: CGFloat = fabs(screenBounds.width - screenBounds.height)

view.frame = CGRectOffset(view.bounds, offset, offset)
contentView.frame = view.bounds
}

override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.All.rawValue)
}

override func shouldAutorotate() -> Bool {
return true
}
}

最后一个技巧是撤消我们应用到窗口的负插图,我们通过将 view 偏移相同的量并将 contentView 视为主视图来实现。

对于您的应用程序,interfaceWindow.rootViewController 将是您的标签栏 Controller ,它又包含一个导航 Controller 等。当您的相机 Controller 出现时,所有这些 View 都需要透明,以便相机窗口可以从它下面显示出来。出于性能原因,您可能会考虑让它们不透明,并且仅在实际使用相机时将所有内容设置为透明,并在不使用时将相机窗口设置为 hidden(同时关闭捕获 session )。

抱歉发小说了;我还没有在其他任何地方看到这个问题,我花了一段时间才弄清楚,希望它能帮助你和任何其他试图获得相同行为的人。即使是 Apple 的 AVCam 示例应用程序也不能很好地处理它。

The example repo I posted还包括已设置相机的版本。祝你好运!

关于ios - 强制 iOS View 不旋转,同时仍允许 subview 旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28278072/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com