簡體   English   中英

iPad 中的 NavigationView 彈出框在 SwiftUI 中無法正常工作

[英]NavigationView in iPad popover does not work properly in SwiftUI

我有以下代碼在點擊按鈕時顯示彈出框:

struct ContentView: View {

    @State private var show = false

    var body: some View {

        Button("Open") {
            self.show.toggle()
        }.popover(isPresented: $show, content: {
//            NavigationView {
                ScrollView {
                    ForEach(0...10, id: \.self) {_ in
                        Text("Test popover ...")
                    }.padding()
                }
//            }
        })

    }
}

在此處輸入圖像描述

如果我在彈出框的內容中添加NavigationView ,那么我會得到:

在此處輸入圖像描述

知道為什么會這樣嗎?

如果我為內容設置一個固定的框架,它工作正常,但我不想這樣做,因為我希望彈出框根據它的內容調整大小。

可能在 iPad 上,他們在尺寸檢測方面遇到了雞蛋問題,因此只需以最低限度完成。

無論如何,解決方案是明確設置.frame ,或者使用預定義的值(對於 iPad 來說還不錯),或者使用動態計算(例如,通過GeometryReader從外框)

這是一個例子。 使用 Xcode 12 / iPadOS 14 測試

演示

struct TestPopover: View {

    @State private var show = false

    var body: some View {
        GeometryReader { gp in
            VStack {
                Button("Open") {
                    self.show.toggle()
                }.popover(isPresented: $show, content: {
                    NavigationView {
                        ScrollView {   // or List
                            ForEach(0...10, id: \.self) {_ in
                                Text("Test popover ...")
                            }.padding()
                        }
                        .navigationBarTitle("Test", displayMode: .inline)
                    }
                    .frame(width: gp.size.width / 3, height: gp.size.height / 3)
                })
            }.frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

變體 2:部分根據外部尺寸計算,部分根據內部尺寸計算。

演示2

struct TestPopover: View {

    @State private var show = false
    @State private var popoverWidth = CGFloat(100)

    var body: some View {
        GeometryReader { gp in
            VStack {
                Button("Open") {
                    self.show.toggle()
                }.popover(isPresented: $show, content: {
                    NavigationView {
                        ScrollView {   // or List
                            ForEach(0...10, id: \.self) {_ in
                                Text("Test popover ...").fixedSize()
                            }.padding()
                            .background(GeometryReader {
                                Color.clear
                                    .preference(key: ViewWidthKey.self, value: $0.frame(in: .local).size.width)
                            })
                            .onPreferenceChange(ViewWidthKey.self) {
                                self.popoverWidth = $0
                            }
                        }
                        .navigationBarTitle("Test", displayMode: .inline)
                    }
                    .frame(width: self.popoverWidth, height: gp.size.height / 3)
                })
            }.frame(maxWidth: .infinity, maxHeight: .infinity)
        }
    }
}

struct ViewWidthKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

Asperi 的答案很棒而且很徹底,但我想我會為我們中間的懶惰者添加一個。

微小的彈出框 window 是 iPadOS 13.4 中引入的錯誤(彈出框出現在 13.0.x - 13.3.x 中,正如您所期望的那樣)。 我提交了關於它的 FB7640734,它目前顯示“少於 10 個”類似的報告並且仍然開放。

我在一個用 SwiftUI 編寫的生產應用程序中使用的簡單解決方法是在您的 NavigationView 之后添加這個:

.frame(minWidth: 320, idealWidth: 400, maxWidth: nil, minHeight: 500, idealHeight: 700, maxHeight: nil, alignment: .top)

即在OP的示例代碼的上下文中:

struct ContentView: View {

    @State private var show = false

    var body: some View {

        Button("Open") {
            self.show.toggle()
        }.popover(isPresented: $show, content: {
            NavigationView {
                ScrollView {
                    ForEach(0...10, id: \.self) {_ in
                        Text("Test popover ...")
                    }.padding()
                }
            }.frame(minWidth: 320, idealWidth: 400, maxWidth: nil,
                    minHeight: 500, idealHeight: 700, maxHeight: nil,
                    alignment: .top)
        })

    }
}

這將設置一個大小合適的彈出框,它將在 320-400 點寬和 500x700 點高之間擴展,這實際上是彈出框的一個很好的尺寸(任何更大,您可能應該使用彈出框以外的東西)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM