【问题标题】:SwiftUI: How can I navigate to a NavigationLink when there is a Picker on the same Form?SwiftUI:当同一个表单上有一个 Picker 时,我如何导航到 NavigationLink?
【发布时间】:2021-01-21 21:42:54
【问题描述】:

我想在与我的选取器相同的表单行上放置一个“扫描”按钮。扫描仪视图有自己的 NavigationLink,当用户点击 Scan 按钮时应该会弹出它。

实际发生的情况:

Picker 的 NavigationLink 和 Scanner 的 NavigationLink 目标视图同时出现。当您点击 Picker 或 Scan 按钮时,您将随机看到两个目的地之一(假设一个在 z 顺序中位于另一个之上)。

下面是它的样子:

这是重现此问题的代码...

    struct Truck: Hashable, Identifiable {
        var id: String
        var color: String
        var assetId: String
    }
    
    
    struct ContentView: View
    {
        var trucks = [
            Truck(id: "a", color: "Red", assetId: "1"),
            Truck(id: "b", color: "Green", assetId: "2"),
            Truck(id: "c", color: "Blue", assetId: "3")
        ]
        @State private var myTruck: Truck?
        
        var body: some View {
            GeometryReader { geometry in
                NavigationView {
                    Form {
                        HStack {
                            Picker("Choose a truck", selection: $myTruck) {
                                ForEach(trucks) { truck in
                                    Text(truck.color).tag(Optional.some(truck.self))
                                }
                            }
                            .frame(maxWidth: (geometry.size.width * 0.5))
                            .clipped()
                            Scanner(callback: { barcode in
                                myTruck = trucks.filter { $0.assetId == barcode }.first
                            })
                        }
                    }
                }
            }
        }
    }
    
    
    struct Scanner: View {
        @State private var isShowingScanner: Bool = false
        var callback: (String)->()
        var body: some View {
            ZStack { // makes NavigationLink not visible.
                NavigationLink(destination: Button("Scan 3 example", action: {
                    callback("3")
                    self.isShowingScanner = false
                }), isActive: $isShowingScanner) {
                    EmptyView()
                }
                .frame(width: 0, height: 0)
                Button("Scan", action: {
                    isShowingScanner = true
                })
            }
        }
    }

我想要发生的是,如果您点击选择器,则会出现选项列表。如果您点击扫描按钮,扫描仪窗口应该会出现。我考虑过为各种目的地视图使用标签,但我不知道如何在 Picker 的目的地上执行此操作。另外,扫描仪是一个单独的组件,所以我认为它可以控制自己的 NavigationLink。

XCode 12.3 斯威夫特 5 iOS 14.3

【问题讨论】:

    标签: forms swiftui picker swiftui-navigationlink


    【解决方案1】:

    解决方案实际上非常简单。选择器需要放在小于行宽的框架中,然后进行裁剪。否则,它将在整行中可选。我通常使用 GeometryReader 来获得每个设备的正确比例。假设使用名为几何的代理声明 GeometryReader,您的行将如下所示:

    HStack {
        Picker("Choose a truck", selection: $myTruck) {
            ForEach(trucks) { truck in
                 Text(truck.color).tag(Optional.some(truck.self))
            }
        }
        .frame(width: (geometry.size.width * 0.5)) // uses 50% of the row. You can
                                                   // make it any size you want.
        .clipped()
    
        Scanner(callback: { barcode in
            myTruck = trucks.filter { $0.assetId == barcode }.first
        })
    }
    

    【讨论】:

    • 我明白你在说什么,因为当我添加你的 .frame 和 .clipped 代码(并包装在 GeometryReader 中)时,它会改变布局。不幸的是,如果我注释掉扫描仪的导航视图,即使我在选择器区域之外点击,选择器的目的地也会出现。
    • 我将此 .frame 和 .clipped 代码添加到我的原始答案中,因此如果有人尝试,他们将看到该行为。选择器目的地是否会显示似乎没有区别。即使出现 Scanner NavigationLink 目的地,然后您点击“Scan 3 example”按钮,选择器的目的地也是可见的。它应该只是回到主视图。
    猜你喜欢
    • 2020-03-31
    • 2021-07-01
    • 1970-01-01
    • 2020-10-04
    • 1970-01-01
    • 2018-01-26
    • 2022-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多