我有一个带有两个选项卡的 SwiftUI TabView,其中一个选项卡使用 NavigationLink 呈现一个子视图。我想要实现的是,当我点击父视图(呈现子视图的选项卡)的选项卡项时,它应该关闭子视图并返回到父视图。
struct ContentView: View {
var body: some View {
TabView {
NavigationView {
VStack {
Text("View1")
NavigationLink {
Text("Child View")
} label: {
Text("Go to child view")
}
}
}
// when child view is presented, I want when I tap on the tab item view the child view to dismiss. How can I achieve this?
.tabItem {
Label("view1", systemImage: "1.circle")
}
Text("View2")
.tabItem {
Label("view2", systemImage: "2.circle")
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试了各种方法,包括使用 .onChange 和 @Environment(.presentationMode),但我无法使其按预期工作。
当使用 TabView 并呈现子视图时,有没有办法在 SwiftUI 中实现这种行为?任何帮助或指导将不胜感激。
至少有两种方法可以实现你想要的:
.id()API 重置NavigationLink.enum TabSelection {
case first
case second
}
private final class ContentViewModel: ObservableObject {
@Published var tabSelection = TabSelection.first
}
struct ContentView: View {
@StateObject private var viewModel = ContentViewModel()
@State private var tab0Id = UUID()
var body: some View {
TabView(selection: $viewModel.tabSelection) {
NavigationView {
VStack {
Text("View1")
NavigationLink {
Text("Child View")
} label: {
Text("Go to child view")
}
.id(tab0Id)
}
}
.tag(TabSelection.first)
.tabItem {
Label("view1", systemImage: "1.circle")
}
Text("View2")
.tabItem {
Label("view2", systemImage: "2.circle")
}
.tag(TabSelection.second)
}
.onReceive(viewModel.$tabSelection) { newValue in
if newValue == .first {
tab0Id = UUID()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
EnvironmentObject到子视图中:enum TabSelection {
case first
case second
}
private final class ContentViewModel: ObservableObject {
@Published var tabSelection = TabSelection.first
}
struct ContentView: View {
@StateObject private var viewModel = ContentViewModel()
var body: some View {
TabView(selection: $viewModel.tabSelection) {
NavigationView {
VStack {
Text("View1")
NavigationLink {
ChildView()
} label: {
Text("Go to child view")
}
}
}
.tag(TabSelection.first)
.tabItem {
Label("view1", systemImage: "1.circle")
}
Text("View2")
.tabItem {
Label("view2", systemImage: "2.circle")
}
.tag(TabSelection.second)
}
.environmentObject(viewModel)
}
}
struct ChildView: View {
@Environment(\.dismiss) private var dismiss: DismissAction
@EnvironmentObject private var rootViewModel: ContentViewModel
var body: some View {
Text("Child View")
.onReceive(rootViewModel.$tabSelection) { newValue in
if newValue == .first {
dismiss()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
编辑:只是一个旁注:如果您只需要在第一个选项卡上并点击第一个选项卡项时重置导航,您只需更改逻辑,如下所示onReceive:
.onReceive(viewModel.$tabSelection) { [oldValue = viewModel.tabSelection] newValue in
if oldValue == .first && newValue == .first {
tab0Id = UUID() // or `dismiss()` if you prefer the second way I described here above
}
}
Run Code Online (Sandbox Code Playgroud)
结果是:
| 归档时间: |
|
| 查看次数: |
226 次 |
| 最近记录: |