您只需要使用一个级别NavigationView
。换句话说,你不应该嵌套NavigationViews
。看看这个答案。
自定义导航栏 SwiftUI 上仅可见后退按钮 https://stackoverflow.com/questions/68117105/only-back-button-visible-on-custom-navigation-bar-swiftui
- Use a
NavgationView
为了MasterView
正如你所使用的。
- Use a
NavigationView
对于每个Tab#
veiws.
- 之间切换
MasterView
and DetailsView
.
- Use
Button
代替NavigationLink
in MasterView
(您可以将其自定义为看起来像NavigationLink
)
- 在每个中使用自定义后退按钮
Tab#
veiws.
这控制哪一个MasterView
and DetailsView
应该显示。
class BaseViewModel: ObservableObject {
@Published var userFlow: UserFlow = .masterView
init(){
userFlow = .masterView
}
enum UserFlow {
case masterView, detailsView
}
}
该视图可用于ContentView
或者代替它。当你在MasterView
然后单击列表行之一,设置appState.userFlow = .detailView
。当您单击后退按钮时,设置appState.userFlow = .masterView
.
这样做,您可以在两个视图和一个视图之间切换NavigationView
一次显示。
截至目前,它还没有动画。如果您愿意,请使用
https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions https://developer.apple.com/tutorials/swiftui/animating-views-and-transitions
struct BaseView: View {
@EnvironmentObject var appState: BaseViewModel
@State var index: Int = 0
var body: some View {
Group {
switch appState.userFlow {
case .masterView:
MasterView(index: $index)
default:
DetailView(index: index)
}
}
.edgesIgnoringSafeArea(.bottom)
}
}
完整代码
struct ContentView: View {
var body: some View {
BaseView().environmentObject(BaseViewModel())
}
}
class BaseViewModel: ObservableObject {
@Published var userFlow: UserFlow = .masterView
init(){
userFlow = .masterView
}
enum UserFlow {
case masterView, detailsView
}
}
struct BaseView: View {
@EnvironmentObject var appState: BaseViewModel
@State var index: Int = 0
var body: some View {
Group {
switch appState.userFlow {
case .masterView:
MasterView(index: $index)
default:
DetailView(index: index)
}
}
.edgesIgnoringSafeArea(.bottom)
}
}
struct MasterView: View {
@EnvironmentObject var appState: BaseViewModel
@Binding var index: Int
var body: some View {
NavigationView {
List {
ForEach(0..<20) { index in
Button(action: {
appState.userFlow = .detailsView
$index.wrappedValue = index
}, label: {
HStack {
Text("\(index) th row")
Spacer()
Image(systemName: "greaterthan")
}
})
.tag(index)
}
}.navigationTitle(Text("Ratty"))
}
}
}
struct DetailView: View {
var index: Int
@State var selectedTab = 1
var body: some View {
TabView(selection: $selectedTab) {
Tab1(index: index).tabItem { Label("Tab1", systemImage: "list.dash") }
Tab2(index: index).tabItem { Label("Tab2", systemImage: "aqi.medium") }
Tab3(index: index).tabItem { Label("Tab3", systemImage: "move.3d") }
}
}
}
struct Tab1: View {
@EnvironmentObject var appState: BaseViewModel
var index: Int
var body: some View {
NavigationView {
Text("This is \(index) in tab 1")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("back") { appState.userFlow = .masterView }
}
ToolbarItem(placement: .navigationBarTrailing) {
Button("Bingo") { print("Bingo") }
}
}
}
}
}
struct Tab2: View {
@EnvironmentObject var appState: BaseViewModel
var index: Int
var body: some View {
NavigationView {
Text("This is \(index) in tab 2")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("back") { appState.userFlow = .masterView }
}
ToolbarItem(placement: .primaryAction) {
Button("Bongo") { print("Bongo") }
}
}
}
}
}
struct Tab3: View {
@EnvironmentObject var appState: BaseViewModel
var index: Int
var body: some View {
NavigationView {
Text("This is \(index) in tab 3")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button("back") { appState.userFlow = .masterView }
}
ToolbarItem(placement: .primaryAction) {
Button("Banjo") { print("Banjo") }
}
}
}
}
}
我已经定制了xtwistedx https://stackoverflow.com/users/12417531/xtwistedx 's solution https://stackoverflow.com/questions/68117105/only-back-button-visible-on-custom-navigation-bar-swiftui.