SwiftUI:单击按钮时如何呈现视图?
SwiftUI: How to present view when clicking on a button?
我正在尝试使用 Apple 的 SwiftUI 制作一个应用程序,我需要有两个按钮在单个 List
行中显示两个不同的视图。
我使用 Xcode beta 7 和 MacOS 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()
视图出现,但在这两种情况下,它没有出现。
更新: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)
}
}
}
改进版。 (Swift, iOS 13 测试版 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
大大改进的版本(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()
}
}
}
我正在尝试使用 Apple 的 SwiftUI 制作一个应用程序,我需要有两个按钮在单个 List
行中显示两个不同的视图。
我使用 Xcode beta 7 和 MacOS 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()
视图出现,但在这两种情况下,它没有出现。
更新: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)
}
}
}
改进版。 (Swift, iOS 13 测试版 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
大大改进的版本(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()
}
}
}