应用程序的主要视图是具有 2 个屏幕的 TabView。
我需要创建一个入门视图(有很多),它们位于自己的 NavigationStack 中。入门视图仅在首次启动时显示。
如果我可以将 Onboarding View 像 TabView 的项目一样放置,带有“0”标签,但在 TapBar 上不显示图标,那将非常适合设计要求。
我的意思是,当打开我的 TabView 时,其中不应该有 OnboardingView(即 .tag(0))。但我可以将应用程序的逻辑设置为在首次启动时在 .tag(0) 上打开,并在每次启动时在 .tag(1) 上打开。
当然,我会隐藏 OnboardingView 上的 tapBar。
TabView(selection: $vm.tabSelection,
content: {
OnboardingView()
.tag(0)
FirstView()
.tabItem {
Image(systemName: "sparkles")
Text("SecondView")
}
.tag(1)
SecondView()
.navigationTitle("SecondView")
.tabItem {
Text("Remove BG")
Image(systemName: "eraser.line.dashed")
}
.tag(2)
}
...
正如我在评论中建议的那样,您可以使用
TabView
作为顶级父视图,在入门视图和 ZStack
之间切换。
您说这行不通,因为您在
FirstView
中使用了弹出框和弹出框提示。下面的独立示例表明它实际上可以工作。
我遇到的唯一问题是,在入门和
.move
之间使用 TabView
过渡时,弹出框提示未以正确的宽度显示。但是当使用(默认)不透明度过渡时,它工作得很好。
struct ContentView: View {
@State private var onboardingDone = false
@State private var tabSelection = 1
var body: some View {
ZStack {
if onboardingDone {
TabView(selection: $tabSelection) {
FirstView(onboardingDone: $onboardingDone)
.tabItem {
Image(systemName: "sparkles")
Text("SecondView")
}
.tag(1)
SecondView()
.tabItem {
Text("Remove BG")
Image(systemName: "eraser.line.dashed")
}
.tag(2)
}
} else {
OnboardingView(onboardingDone: $onboardingDone)
}
}
}
}
struct OnboardingView: View {
@Binding var onboardingDone: Bool
var body: some View {
NavigationStack {
NavigationLink("Go to next") {
VStack(spacing: 50) {
Text("Onboarding completed")
Button("Ready for FirstView") {
withAnimation {
onboardingDone = true
}
}
.buttonStyle(.bordered)
}
}
.navigationTitle("OnboardingView")
}
}
}
struct FirstView: View {
@Binding var onboardingDone: Bool
struct QuickTip: Tip {
var title: Text {
Text("Want to onboard again?")
}
var message: Text? {
Text("The button to reset the onboarding is in the next view")
}
var image: Image? {
Image(systemName: "hand.thumbsup.circle")
}
}
var body: some View {
NavigationStack {
NavigationLink("Go to next") {
VStack(spacing: 50) {
Text("Child of FirstView")
Button("Reset onboarding") {
withAnimation {
onboardingDone = false
}
}
.buttonStyle(.bordered)
}
}
.popoverTip(QuickTip())
.onAppear {
try? Tips.resetDatastore()
try? Tips.configure()
}
.navigationTitle("FirstView")
}
}
}
struct SecondView: View {
@State private var isShowingPopover = false
var body: some View {
NavigationStack {
NavigationLink("Go to next") {
VStack(spacing: 50) {
Text("Child of SecondView with Popover")
.onTapGesture {
isShowingPopover.toggle()
}
.popover(isPresented: $isShowingPopover, arrowEdge: .bottom) {
Text("Interesting popover")
.padding()
.presentationCompactAdaptation(.popover)
}
}
}
.navigationTitle("SecondView")
}
}
}