我的应用程序具有根据设备设置的某些方向。 对于 iPad,它设置为横向;对于 iPhone,它设置为纵向。 这工作得很好,除了我想允许 iPhone 横向显示一个视图。 我需要视图自动旋转为横向并在离开该视图后旋转回纵向。 我有以下代码可以锁定该视图的方向,但必须手动来回旋转设备。有没有办法自动旋转设备?
.onAppear {
if(deviceType == .phone){
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
AppDelegate.orientationLock = .landscape
}
}
.onDisappear {
if(deviceType == .phone){
AppDelegate.orientationLock = .portrait
}
}
这可以使用
View extension
来实现,它将更新视图的方向。让我们制作自己的扩展,它将在给定方向上来回 rotate
view
。
extension View {
@ViewBuilder
func forceRotation(orientation: UIInterfaceOrientationMask) -> some View {
if UIDevice.current.userInterfaceIdiom == .phone {
self.onAppear() {
AppDelegate.orientationLock = orientation
}
// Reset orientation to previous setting
let currentOrientation = AppDelegate.orientationLock
self.onDisappear() {
AppDelegate.orientationLock = currentOrientation
}
} else {
self
}
}
}
在AppDelegate中,添加:
class AppDelegate: NSObject, UIApplicationDelegate {
static var orientationLock = UIInterfaceOrientationMask.portrait {
didSet {
if #available(iOS 16.0, *) {
UIApplication.shared.connectedScenes.forEach { scene in
if let windowScene = scene as? UIWindowScene {
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: orientationLock))
}
}
UIViewController.attemptRotationToDeviceOrientation()
} else {
if orientationLock == .landscape {
UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
} else {
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
}
}
}
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
return true
}
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return AppDelegate.orientationLock
}
}
这个小例子演示了如何使用此扩展:
struct ContentView: View {
var body: some View {
NavigationView {
List(Orientation.allCases, id: \.self) { orientation in
NavigationLink(orientation.title) {
ZStack {
Text(orientation.title)
}
.forceRotation(orientation: orientation.mask) // << Update the required orientation here..
}
}
}
}
}
enum Orientation: Int CaseIterable {
case landscapeLeft
case landscapeRight
var title: String {
switch self {
case .landscapeLeft:
return "LandscapeLeft"
case .landscapeRight:
return "LandscapeRight"
}
}
var mask: UIInterfaceOrientationMask {
switch self {
case .landscapeLeft:
return .landscapeLeft
case .landscapeRight:
return .landscapeRight
}
}
}
Kush Bhavsar 的答案几乎对我有用,但当视图消失时它无法恢复到之前的方向。这是一个确实按预期恢复到以前的方向的解决方案(并且我改进了一些内容的命名和组织以使其更加清晰)。
创建视图扩展
supportedInterfaceOrientations
:
extension View {
@ViewBuilder func supportedInterfaceOrientations(
_ orientations: UIInterfaceOrientationMask
) -> some View {
modifier(SupportedInterfaceOrientationsModifier(orientations: orientations))
}
}
private struct SupportedInterfaceOrientationsModifier: ViewModifier {
let orientations: UIInterfaceOrientationMask
@State private var previousOrientations = UIInterfaceOrientationMask.portrait
func body(content: Content) -> some View {
content
.onAppear() {
previousOrientations = AppDelegate.supportedInterfaceOrientations
AppDelegate.supportedInterfaceOrientations = orientations
}
.onDisappear() {
AppDelegate.supportedInterfaceOrientations = previousOrientations
}
}
}
在AppDelegate中,添加静态变量:
static var supportedInterfaceOrientations = UIInterfaceOrientationMask.portrait {
didSet { updateSupportedInterfaceOrientationsInUI() }
}
并添加 AppDelegate 扩展:
extension AppDelegate {
private static func updateSupportedInterfaceOrientationsInUI() {
if #available(iOS 16.0, *) {
UIApplication.shared.connectedScenes.forEach { scene in
if let windowScene = scene as? UIWindowScene {
windowScene.requestGeometryUpdate(
.iOS(interfaceOrientations: supportedInterfaceOrientations)
)
}
}
UIViewController.attemptRotationToDeviceOrientation()
} else {
if supportedInterfaceOrientations == .landscape {
UIDevice.current.setValue(
UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation"
)
} else {
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
}
}
}
func application(
_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?
) -> UIInterfaceOrientationMask {
Self.supportedInterfaceOrientations
}
}