SwiftUI:如何在 IOS 16 上动态忽略安全区域

问题描述 投票:0回答:2

我正在寻找 SwiftUI 解决方案来动态更改 IOS 16 中的视图/应用程序的全屏。为简单起见,考虑一个按钮将切换是否全屏。我试过使用绑定值;

 var body : some View {
   
   @Binding var fullScreen  = false
   HStack() {

       Button(action: {
          fullScreen.toggle()
       }) {
          Text("Fullscreen Toggle")
       }
   }
   .edgesIgnoringSafeArea(fullScreen == true ? [.all] : [])

 }

这是解决它的尝试,不幸的是,没有这样的模式(运行时);

invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on 
_CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.
  1. 我们如何动态地忽略安全区域以进入全屏并返回视图。
  2. 如果可能的话,我们可以做一个应用程序范围的解决方案而不是单一视图吗?

注意解决方案必须在IOS 16.

ios swiftui fullscreen
2个回答
0
投票

... to dynamically ignoring safe areas on IOS 16
,尝试这种非常简单的方法,在视图的
@Binding var fullScreen: Bool
之外有
body
。 并从父视图传递绑定,如图所示。

对我来说效果很好,在 MacOS 13.3 上,使用 Xcode 14.3 beta,在真正的 ios 16 设备和 macCatalyst 上测试过。

struct ContentView: View {
    @State var fullScreen = false // <-- here
    var body : some View {
        TestView(fullScreen: $fullScreen)  // <-- here
    }
}

struct TestView: View {
    @Binding var fullScreen: Bool  // <-- here
    
    var body : some View {
        ZStack {
            Color(.yellow)
               .edgesIgnoringSafeArea(fullScreen ? [.all] : [])  // <-- here
            Button("Change edgesIgnoringSafeArea") {
                fullScreen.toggle()
            }
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        // .edgesIgnoringSafeArea(fullScreen ? [.all] : [])  // <-- or here
    }
}

0
投票

也许这个解决方案会有帮助?

import SwiftUI

@main
struct MyFullScreenApp: App {
@State private var isFullScreen = false

var body: some Scene {
    WindowGroup {
        ContentView(isFullScreen: $isFullScreen)
            .frame(maxWidth: .infinity, maxHeight: .infinity)
    }
    .onChange(of: isFullScreen) { newValue in
        UIApplication.shared.windows.first?.rootViewController?.setNeedsStatusBarAppearanceUpdate()
    }
}}

struct ContentView: View {
@Binding var isFullScreen: Bool
var body: some View {
    VStack {
        Text("This is some content")
        Button(action: {
            isFullScreen.toggle()
        }) {
            Text("Toggle Fullscreen")
        }
    }
    .frame(maxWidth: .infinity, maxHeight: .infinity)
    .background(Color.white)
    .edgesIgnoringSafeArea(isFullScreen ? .all : [])
    .statusBar(hidden: isFullScreen)
    .navigationViewStyle(.stack)
}}

要启用全屏模式,我们使用带有 .all 选项的 .edgesIgnoringSafeArea() 修饰符,并使用 .statusBar(hidden:) 修饰符隐藏状态栏。请注意,如果您的视图嵌入在 NavigationView 中,这也会隐藏导航栏。

为了使它成为您应用程序的全局解决方案,您可以创建自定义 AppDelegate 并将 window 属性的 rootViewController 设置为包装您的 ContentView 的新 UIHostingController 实例。然后你可以使用相同的方法来切换全屏模式。

© www.soinside.com 2019 - 2024. All rights reserved.