SwiftUI:如何在点击按钮时呈现视图?

6

我正在使用苹果的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()视图出现,但在这两种情况下都没有出现。

我所说的“present”是用AddList()视图替换默认视图。就像你通常使用NavigationButton一样。所以,正如你所说,我的目标是导航到不同的界面。正如我所写的,我还尝试在navigationButton内部添加navigationButton,但它没有起作用。我的问题可能不太清楚,我想做的是,当点击“编辑”按钮时,导航到不同的界面(AddList()界面),当我在行中的其他地方单击时,导航到“ContentOfList()”界面。 - Christophe Prat
谢谢,您有没有关于如何解决在导航按钮内添加导航按钮的问题的想法? - Christophe Prat
@matt,使用DynamicNavigationDestinationLink是完全可能的。我在下面发布了我的答案。 - kontiki
我认为他们在 Beta 5 中终于做对了。请看下面我的回答。 - Chuck H
3个回答

7

更新版本(SwiftUI,iOS 13 beta 7)得到了大幅改进。

同样的解决方案也适用于使用.sheet修饰符呈现的模态视图的关闭。

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 中图片的蓝色背景吗? - Christophe Prat
@ChristophePrat 图像上的.renderingMode - Andre Carrera

5

更新:NavigationButton的生命周期非常短暂,在beta3中已经被弃用。我正在更新代码以使用其替代品:NavigationLink.

您可以从三个地方展示视图,这里是如何做到的:

enter image description here

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。 - kontiki
这很聪明,但你没有导航到三个不同的视图。你是在导航到具有三个不同数据字符串的同一视图。 - matt
@matt 这只是一个通用的例子。你总是可以扩展它来使用不同的视图。或者我没有理解你的意思? - kontiki
@kontiki,实际上,我不明白你如何使用DynamicNavigationDestinationLink切换到三个不同的视图。 - Christophe Prat
嗨@ChristophePrat,我更新了代码以导航到三个不同的视图,具体取决于用户点击的位置(行、编辑按钮或加号按钮)。 - kontiki
显示剩余2条评论

1
改进版。(Swift,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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接