【问题标题】:SwiftUI: How to present view when clicking on a button?SwiftUI:单击按钮时如何呈现视图?
【发布时间】:2019-11-13 04:22:11
【问题描述】:

我正在尝试使用 Apple 的 SwiftUI 制作一个应用程序,我需要有两个按钮在单个 List 行中呈现两个不同的视图。

我使用 Xcode beta 7MacOS Catalina beta 7。我尝试添加一个显示视图的Button,但是我无法单击它,当我在List 之外尝试一个简单的Button 并单击它时,AddList() 视图没有出现.我也尝试在navigationButton 中添加navigationButton,但它也没有奏效。添加tapAction也不起作用,当你点击它时,视图仍然没有出现

NavigationView {
            List(0..<5) { item in
                NavigationLink(destination: ContentOfList()) {
                    Text("hello") // dummy text
                    Spacer()
                    Text("edit")
                        .tapAction {
                            AddList() // This is the view I want to present
                    }
                }
                }.navigationBarItems(trailing: NavigationLink(destination: AddList(), label: { // doesn't work within navigationBarItems
                    Image(systemName: "plus.circle.fill")
                }))
        }

我希望 AddList() 视图会出现,但在这两种情况下,它不会出现。

【问题讨论】:

  • 我所说的“现在”是用 AddList() 视图替换默认视图。就像您通常使用 NavigationButton 所做的一样。所以正如你所说,我的目标是导航到不同的界面。正如我所写的,我也尝试在 navigationButton 中添加一个 navigationButton 但它没有用。我的问题可能不清楚,我想要做的是,单击“编辑”按钮时,导航到不同的界面(AddList() 界面),当我单击行中的其他位置时,导航到“ ContentOfList()' 接口。
  • 谢谢,您知道如何解决在 navigationButton 中添加 navigationButton 的问题吗?
  • @matt 实际上可以使用 DynamicNavigationDestinationLink。我在下面发布了我的答案。
  • 我认为他们终于在 Beta 5 中做到了。请参阅下面的答案。

标签: swift swiftui swiftui-navigationlink


【解决方案1】:

大大改进的版本(SwiftUI、iOS 13 beta 7)

同样的解决方案也适用于解除带有 .sheet 修饰符的 Modals。

import SwiftUI

struct DetailView: View {
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    var body: some View {
        Button(
            "Here is Detail View. Tap to go back.",
            action: { self.presentationMode.wrappedValue.dismiss() }
        )
    }
}

struct RootView: View {
    var body: some View {
        VStack {
            NavigationLink(destination: DetailView())
            { Text("I am Root. Tap for Detail View.") }
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            RootView()
        }
    }
}

【讨论】:

  • 谢谢。实际上它非常棒。您知道是否有任何方法可以禁用 NavigationLink 的蓝色背景(在图片上)?
  • @ChristophePrat .renderingMode 在图片上
【解决方案2】:

更新:NavigationButton 的寿命很短。在 beta3 中,它已被弃用。我正在更新代码以使用它的替换:NavigationLink

您可以从所有三个位置呈现视图。方法如下:

import SwiftUI

struct ContentView: View {

    var body: some View {
        NavigationView {
            TopView().navigationBarTitle(Text("Top View"))
        }
    }
}

struct TopView: View {
    @State private var viewTypeA = true

    let detailViewA = DynamicNavigationDestinationLink(id: \String.self) { data in
            ListA(passedData: data)
    }

    let detailViewB = DynamicNavigationDestinationLink(id: \String.self) { data in
            ListB(passedData: data)
    }

    var body: some View {
            List(0..<5) { item in
                NavigationLink(destination: ListC(passedData: "FROM ROW #\(item)")) {
                    HStack {
                        Text("Row #\(item)")
                        Spacer()
                        Text("edit")
                            .tapAction {
                                self.detailViewA.presentedData?.value = "FROM TAP ACTION Row #\(item)"
                        }
                    }
                }
            }.navigationBarItems(trailing: Button(action: {
                            self.detailViewB.presentedData?.value = "FROM PLUS CIRCLE"
            }, label: {
                    Image(systemName: "plus.circle.fill")
                }))
    }
}

struct ListA: View {
    let passedData: String

    var body: some View {
        VStack {
            Text("VIEW A")
            Text(passedData)
        }
    }
}

struct ListB: View {
    let passedData: String

    var body: some View {
        VStack {
            Text("VIEW B")
            Text(passedData)
        }
    }
}

struct ListC: View {
    let passedData: String

    var body: some View {
        VStack {
            Text("VIEW C")
            Text(passedData)
        }
    }
}

【讨论】:

  • 更新答案以包含动画 gif。
  • 这很聪明,但您不会导航到三个不同的视图。您正在导航到具有三个不同数据字符串的同一视图。
  • @matt 这是一个通用示例。您始终可以扩展它以对每个视图使用不同的视图。还是我错过了你的意思?
  • @kontiki 实际上,我不明白如何使用 DynamicNavigationDestinationLink 移动到三个不同的视图
  • 嗨@ChristophePrat,我更新了代码以导航到三个不同的视图,具体取决于用户点击的位置(行、编辑按钮或加号按钮)。
【解决方案3】:

改进版。 (斯威夫特,iOS 13 beta 4)

class NavigationModel : BindableObject {
    var willChange = PassthroughSubject<Void, Never>()
    var presentedData: String? {
        didSet {
            willChange.send()
        }
    }
    func dismiss() { if presentedData != nil {
        presentedData = nil
    } }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            MasterView()
        }.environmentObject(NavigationModel())
    }
}

struct MasterView: View {

    @EnvironmentObject
    var navigationModel: NavigationModel
    var destinationLink = DynamicNavigationDestinationLink<String, String, DetailView>(id: \.self) { data in DetailView(data: data) }

    var body: some View {
        List(0..<10) { index in
            Button("I am root. Tap for more details of #\(index).") {
                self.navigationModel.presentedData = "#\(index)"
            }
        }
        .navigationBarTitle("Master")
        .onReceive(navigationModel.willChange) {
            self.destinationLink.presentedData?.value = self.navigationModel.presentedData
        }
    }
}

struct DetailView: View {
    @EnvironmentObject
    var model: NavigationModel

    let data: String

    var body: some View {
        Button("Here are details of \(data). Tap to go back.") {
            self.model.dismiss()
        }
        .navigationBarTitle("Detail \(data)")
    }
}

struct Empty : Hashable {
}


#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
#endif

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-22
    相关资源
    最近更新 更多