SwiftUI,NavigationView旋转消失吗?

时间:2020-01-06 20:24:09

标签: swiftui

我试图弄清楚为什么旋转设备会使内容消失。

这是我正在运行的确切代码:

struct ContentView: View {
    @State private var selection = 0

    init() {

    }

    var body: some View {

        NavigationView {

            VStack {
                Button(action: {

                }) {
                    Text("Tap me")
                    .padding()
                    .foregroundColor(.white)
                    .background(Color.blue)
                    .cornerRadius(8)
                }.shadow(color: Color.blue, radius: 20, y: 5)
                    .frame(width: 300, height: 100, alignment: .trailing)

                Text("SwiftUI")
                    .navigationBarTitle("Nav Title")
            }

            Color.red.edgesIgnoringSafeArea([.top,.bottom,.leading,.trailing])

        }

    }
}

enter image description here

如何解决此问题,以便旋转设备以保持内容可见?

在“ Liem Vo”回答后提供更多反馈。

如果我在iPhone 11 Pro上而不是在max上运行代码,那么它将起作用。 enter image description here

在最大速度下运行时,“主视图”会从屏幕向左横向移出,可以通过滑动将其拉入。我并没有在SwiftUI中使用NavigationView意识到这种行为,所以这就是我的目的。

这是MAX上的行为,没有“ Liem Vo”建议的修复程序: enter image description here

2 个答案:

答案 0 :(得分:0)

我想根据现有解决方案提出一个改进的版本。它只是扩展了现有的StackNavigationViewStyle()修饰符并添加了 condition ,而不是在iPhone上将其硬编码为.navigationViewStyle(),以便您可以决定哪种样式根据视图的sizeClass使用。这很重要,因为iPad上的应用程序有时必须以“ iPhone”大小显示,并且仅基于UIUserInterfaceIdiom来确定导航样式是不够的!

extension View {
    public func navigationViewStyle<S>(_ style: S, condition: Bool) -> some View where S : NavigationViewStyle {
        if condition {
            return AnyView(self.navigationViewStyle(style))
        } else {
            return AnyView(self)
        }
    }
}

您将像这样使用它:

struct ListView: View {
    @Environment(\.horizontalSizeClass) var horizontalSizeClass: UserInterfaceSizeClass?
    @Environment(\.verticalSizeClass) var verticalSizeClass: UserInterfaceSizeClass?
    
    var body: some View {
        NavigationView {
            List(0 ..< 5) {
                Text("Hello, World!")
            }
            .navigationViewStyle(StackNavigationViewStyle(), condition: horizontalSizeClass != .regular && verticalSizeClass != .regular)
        }
    }
}

这将导致当StackNavigationViewStyle()不是sizeClass(iPhone)时应用.regular,而当DoubleColumnNavigationViewStyle()是{{1}时默认sizeClass被应用},例如在全屏应用中的iPad上。

答案 1 :(得分:0)

以上所有答案都不是很完整,所以我想补充一下,因为我研究了这个问题很长时间,这就是我得出的结论。我认为它会很有用:

导航视图的一个有趣之处在于它如何在大型设备(通常是 iPhone 和大型 iPad)上执行分屏功能。

var body: some View {
        NavigationView {
            Text("Primary")
        }
    }

如果将 iPhone 11 ProMax 旋转到横向(Cmd + ->),您会看到文本视图消失了。

SwiftUI 会自动考虑横向导航视图并显示 DetailView 而不是 main(“主要”)。

您可以通过在 NavigationView 中提供两个视图来解决 SwiftUI 期望的问题,例如:

var body: some View {
        NavigationView {
            Text("Primary")
            Text("Secondary")
        }
    }

由于本人名气不大,所以只能发个带链接的照片(如果我的帖子有用,请给个好评): enter image description here

这就是为什么我们添加. navigation Bar Title(Text ("Test"), displayMode:. inline)

时会抛出错误“无法同时满足约束”的原因

因此,解决方法如下:

  1. 向导航视图添加第二个视图

在这里,当你旋转屏幕时,屏幕 #2 - Text("Secondary") 将被显示。

    var body: some View {
            NavigationView {
                Text("Primary")
                Text("Secondary")
            .navigationBarTitle(Text("Test"), displayMode: .inline)
            }
    }
  1. 修饰符 .navigationViewStyle(StackNavigationViewStyle())

但是,如果要明确指定旋转时始终显示第一个屏幕(Text("Primary")),则需要添加 .navigationViewStyle(StackNavigationViewStyle) modifier()) ,它可以让您始终切换到 Text (“主要”),无论屏幕如何。

var body: some View {
        NavigationView {
            Text("Primary")
            Text("Secondary")
        .navigationBarTitle(Text("Today's Flavors"), displayMode: .inline)
        }
        .navigationViewStyle(StackNavigationViewStyle())

特别适合您的解决方案:

struct Test: View {
    @State private var selection = 0
    
    var body: some View {
        
        NavigationView {
            
            ZStack {
                Color.red.edgesIgnoringSafeArea([.all])
                VStack {
                    Button(action: {
                        
                    }) {
                        Text("Tap me")
                            .padding()
                            .foregroundColor(.white)
                            .background(Color.blue)
                            .cornerRadius(8)
                    }.shadow(color: Color.blue, radius: 20, y: 5)
                    .frame(width: 300, height: 100, alignment: .trailing)
                    
                    Text("SwiftUI")
                        .navigationBarTitle("Nav Title")
                }
            }
            
        }
        // that means only show one view at a time no matter what device I'm working
        .navigationViewStyle(StackNavigationViewStyle())
    }
}

结果:enter image description here

此外,您还可以阅读有关 NavigationView here

的更多信息