I implemented my own tab bar:
struct MainView: View
{
#State var selectedIndex = 0
let icons = ["menucard", "house"]
let iconsNames = ["meniu", "oferte"]
var body: some View{
VStack(spacing: 0){
ZStack{
switch selectedIndex{
case 0:
MeniuListView()
case 1:
ProfileView()
}
Divider()
HStack{
ForEach(0..<2, id: \.self){number in
Spacer()
Button(action: {
self.selectedIndex=number
}, label: {
VStack(spacing: 3){
Image(systemName: icons[number])
.font(.system(size: 25,
weight: .regular,
design: .default))
}
}
}
}
Now the question is how I can hide it if I want to go to a specific view?
What is the best approach to do so?
For example I want to navigate to a login page, but the tab bar does not hide..
This is my ProfileView() that call the login page but the tab bar does not disappear.. How I can hide it?
ProfileView code:
struct ProfileShopView: View {
#State var goToNextScreen : Int? = nil
var body: some View {
NavigationView{
VStack{
Form{
}
NavigationLink(destination: LoginView().navigationBarHidden(true), tag: 1, selection: $goToNextScreen)
{
EmptyView()
}
Button(action: {
goToNextScreen=1
UserDefaults.standard.set(false, forKey: "isLogin")
} //need to hide the tab bar when navigating to login view
}
}
Approach
Use a full screen cover for login view
After sign in login view is dismissed
Use a tab bar
Tap on logout show login view again
Code
Login
struct LoginView: View {
#Environment(\.dismiss) private var dismiss
var body: some View {
ZStack {
Color.yellow
Button("Sign in") {
dismiss()
}
.buttonStyle(.bordered)
}
.ignoresSafeArea()
}
}
Tab
enum TabContent: Int {
case menu
case profile
}
Content
struct ContentView: View {
#State private var selection = TabContent.menu
#State private var isLoginShown = true
var body: some View {
NavigationStack {
TabView(selection: $selection) {
Text("Menu list")
.tabItem {
Label("Menu", systemImage: "list.bullet")
}
.tag(TabContent.menu)
VStack {
Text("Profile view")
Button("Logout") {
isLoginShown = true
}
}
.tabItem {
Label("Profile", systemImage: "person.crop.circle")
}
.tag(TabContent.profile)
}
}
.fullScreenCover(isPresented: $isLoginShown) {
LoginView()
}
}
}
Related
I am having a problem while I want to dismiss a popup (that appears automatically depending on a specific condition) by clicking a button.
This is the PopUp struct:
struct dataPrivacyPopUp: View {
let model: OffersView.Model
let termsOfUseText = "Nutzungsbedingungen"
let privacyPolicyText = "Datenschutzerklärung"
#State var termsOfUseChecked = false
#State var privacyPolicyChecked = false
#State var buttonDisabled = true
#State private var showPopUp: Bool = false
#Binding var showModal: Bool
var body: some View {
ZStack {
if ( model.showPopUp == true) {
// PopUp Window
VStack(alignment: .center){
Image("logo")
.aspectRatio(contentMode: .fill)
.frame(alignment: .center)
.padding()
VStack(alignment: .leading) {
Text((model.acceptance?.salutation)!)
.multilineTextAlignment(.leading)
.padding()
.foregroundColor(Color.black)
Text((model.acceptance?.statement)!)
.multilineTextAlignment(.leading)
.padding()
.foregroundColor(Color.black)
Text((model.acceptance?.declarationIntro)!)
.multilineTextAlignment(.leading)
.padding()
.foregroundColor(Color.black)
if ((model.acceptance?.dpr)! == true) {
VStack(alignment: .leading){
HStack {
CheckBoxView(checked: $privacyPolicyChecked)
HStack(spacing: 0){
Text(R.string.localizable.dataPrivacyPopupText())
.foregroundColor(Color.black)
Button(privacyPolicyText) {
model.openUrl(url: API.privacyPolicyURL)
}
}
}
Text((model.acceptance?.declarationOutro)!)
.multilineTextAlignment(.leading)
.padding()
}
.padding()
Button(action: {
model.setTos()
print("showModal PopUpView2 1: \(showModal)")
self.showModal.toggle()
print("showModal PopUpView2 2: \(showModal)")
}, label: {
Text(R.string.localizable.dataPrivacyButton())
.foregroundColor(Color.white)
.font(Font.system(size: 23, weight: .semibold))
})
.disabled(model.buttonDisabledForOne(privacyPolicyChecked: privacyPolicyChecked, termsOfUseChecked: termsOfUseChecked))
.padding()
}
}
}
// .onAppear(perform: )
.background(Color.white01)
.padding()
}
}
}
}
and this is where I call it (contentView):
struct OffersView: View {
#StateObject var model = Model()
#State private var showingPopUp = false
#State private var showModal = false
#State private var showingAddUser = false
// var showPopup : Bool = true
var body: some View {
NavigationView {
Group {
switch model.sections {
case .loading:
ActivityIndicator(animate: true)
case .success(let sections):
ScrollView(.vertical) {
VStack(alignment: .leading, spacing: 0) {
Text(R.string.localizable.offersHello(model.firstName))
.aplFont(.headline02)
.padding(.bottom, 24)
VStack(spacing: 48) {
ForEach(sections) { section in
OffersSectionView(section: section, model: model)
}
}
}
.useFullWidth(alignment: .leading)
.padding()
}
default:
Color.clear
if ( model.showPopUp == true) {
ZStack {
Color.black.opacity(model.showPopUp ? 0.3 : 0).edgesIgnoringSafeArea(.all)
dataPrivacyPopUp(model: model, showModal: self.$showModal)
.onAppear(perform: {
self.showModal.toggle()
})
}
}
}
}
.navigationBarHidden(true)
.handleNavigation(model.navigationPublisher)
.onAppear(perform: model.onAppear)
.onDisappear(perform: model.onDisappear)
.environment(\.dynamicTypeEnabled, false)
.safariView(isPresented: model.showSafari) {
SafariView(url: model.safariUrl!)
}
}
}
}
I need help about this, I tried the traditional method to set a #Binding variable etc .. but that's not working, the boolean value is changing but the UI is not updating (the popup is not dismissing), thank you
I tried to look at your code - I suggest you simplify it to the bare minimum to exemplify your issue - and it seems that you are using 2 properties to show your pop-up: showingPopUp and showModal. It is quite likely that you are having trouble keeping them both in sync.
For starters, I would suggest to use only one variable, either it is true or false - "a man with two watches never knows what time it is".
For the solution:
If you prefer keeping your ZStack approach, the solution would look something like:
struct MyPrivacy: View {
#Binding var showMe: Bool
var body: some View {
VStack {
Text("The content of the pop-up")
.padding()
Button {
withAnimation {
showMe.toggle()
}
} label: {
Text("Dismiss")
}
}
}
}
struct Offers: View {
#State private var showPopup = false
var body: some View {
NavigationView {
ZStack {
VStack {
Text("View behind the pop-up")
.padding()
Button {
withAnimation {
showPopup.toggle()
}
} label: {
Text("Pop")
}
}
if showPopup {
Color.white
MyPrivacy(showMe: $showPopup)
}
}
}
}
}
If instead you want to go for a more flexible approach, if you are developing for iOS, SwiftUI has a convenient object - Sheets. You can use it as suggested in the documentation, or build a specific struct that manages all the modal views of this type and use your model to handle the presentation.
The process goes like:
Create a struct that will handle all kinds of Sheets of your app.
Add to your view-model the property to present any sheet.
Create the Views that will be the content of each sheet.
Call the .sheet(item:content:) method on each View the requires a sheet.
Here's the sample code:
SheetView handler:
struct SheetView: Identifiable {
// This struct controls what modal view will be presented.
// The enum SheetScreenType can grow to as many as different
// modal views your app needs - add the content in the switch below.
let id = UUID()
var screen: SheetScreenType
#ViewBuilder
var content: some View {
switch screen {
case .dataPrivacy:
DataPrivacy()
default:
EmptyView()
}
}
enum SheetScreenType {
case dataPrivacy
case none
}
}
Presenter in your view-model:
class MyViewModel: ObservableObject {
// This code can fit anywhere within your view-model.
// It controls the presentation of the modal view, which in
// this case is a Sheet.
private let sharedSheet = SheetView(screen: .none)
// Show the selected sheet
#Published var sheetView: SheetView?
var showSheet: SheetView.SheetScreenType {
get {
return sheetView?.screen ?? .none
}
set {
switch newValue {
case .none:
sheetView = nil
default:
sheetView = sharedSheet
}
sheetView?.screen = newValue
}
}
}
Content of your modal view:
struct DataPrivacy: View {
#EnvironmentObject var model: MyViewModel // Pass YOUR model here
var body: some View {
VStack(alignment: .center){
Text("Respecting your privacy, no details are shown here")
.padding()
Button {
print("Anything you need")
// Set the showSheet property of your model to
// present a modal view. Setting it to .none dismisses
// the modal view.
model.showSheet = .none
} label: {
Text("Time do dismiss the modal view")
}
.padding()
}
}
}
Enable your view to listen to your model to present the sheet:
struct OffersView: View {
#ObservedObject var model = MyViewModel() // Pass YOUR model here
var body: some View {
VStack {
Text("Anything you wish")
.padding()
Button {
withAnimation {
// Set the showSheet property of your model to
// present a modal view. Set it to any choice
// among the ones in the SheetScreen.SheetScreenType enum.
model.showSheet = .dataPrivacy
}
} label: {
Text("Tap here for the privacy in modal view")
}
}
// Show a modal sheet.
// Add this property at the top level of every view that
// requires a modal view presented - whatever content it might have.
.sheet(item: $model.sheetView) { sheet in
sheet.content
.environmentObject(model)
}
}
}
Good luck with your project!
can someone Help me with fixing this. I want this code to work such as when I click the Home button on the side menu, it should take me to the Main View("This is the Main View"). I have tried using presenting sheets, however, presenting sheet doesn't look realistic. When the Home button is tapped, everything should disappear and only the Home Screen should come up with the side menu. I have tried writing up this code, however, I couldn't make the home button work. The codes are as below:
import SwiftUI
import Foundation
import Combine
struct Home: View {
#State var showMenu = false
#EnvironmentObject var userSettings: UserSettings
var body: some View {
let drag = DragGesture()
.onEnded {
if $0.translation.width < -100 {
withAnimation {
self.showMenu = false
}
}
}
return NavigationView {
GeometryReader {
geometry in
ZStack(alignment: .leading) {
MainView(showMenu: self.$showMenu)
.frame(width: geometry.size.width, height: geometry.size.height)
.offset(x: self.showMenu ? geometry.size.width/2 : 0)
.disabled(self.showMenu ? true : false)
if self.showMenu {
MenuView()
.frame(width: geometry.size.width/2)
.transition(.move(edge: .leading))
}
}
.gesture(drag)
}
.navigationBarTitle("Pay Data", displayMode: .inline)
.navigationBarItems(leading: (Button(action: {
withAnimation {
self.showMenu.toggle()
}
}){
Image(systemName: "line.horizontal.3")
.imageScale(.large)
}
))
}
}
}
struct MainView: View {
#Binding var showMenu: Bool
#EnvironmentObject var userSettings: UserSettings
var body: some View {
Text("This is Main View")
}
}
struct Home_Previews: PreviewProvider {
static var previews: some View {
Home()
.environmentObject(UserSettings())
}
}
//This is the Menu View. The Home Button is located in this view.
import SwiftUI
import Combine
import Foundation
struct MenuView: View {
#EnvironmentObject var userSettings: UserSettings
#State var showMenu = false
#State var Homevariable = false
var body: some View {
VStack(alignment: .leading) {
Button(action: {
UserDefaults.standard.set(false, forKey: "status")
}) {
(Text(Image(systemName: "rectangle.righthalf.inset.fill.arrow.right")) + (Text("Home")))
}
}
.padding()
.frame(maxWidth: .infinity, alignment: .leading)
.background(Color(red: 32/255, green: 32/255, blue: 32/255))
.edgesIgnoringSafeArea(.all)
}
}
struct MenuView_Previews: PreviewProvider {
static var previews: some View {
MenuView()
.environmentObject(UserSettings())
}
}
//This is the another view. I want the side Menu to appear on this as well, so when I press the Home button it takes me to the Main View("This is the Main View")
import SwiftUI
struct Calculation: View {
var body: some View {
Text("Hello, World!")
}
}
struct Calculation_Previews: PreviewProvider {
static var previews: some View {
Calculation()
}
}
Here you go. You are basically rebuilding a navigation logic, so in MainView you have to switch between the screens and put the side menu over it:
(PS: you can do without GeometryReader)
struct ContentView: View {
#State private var showMenu = false
#State private var selected: SelectedScreen = .home
var body: some View {
NavigationView {
ZStack {
// show selected screen
switch selected {
case .home:
MainView()
.disabled(self.showMenu ? true : false)
case .screen1:
OtherView(screen: 1)
case .screen2:
OtherView(screen: 2)
}
// put menu over it
if self.showMenu {
MenuView(showMenu: $showMenu, selected: $selected)
.transition(.move(edge: .leading))
}
}
.navigationBarTitle("Pay Data", displayMode: .inline)
// .navigationBarItems is deprecated, use .toolbar
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button {
withAnimation {
self.showMenu.toggle()
}
} label: {
Image(systemName: "line.horizontal.3")
.imageScale(.large)
}
}
}
}
}
}
enum SelectedScreen {
case home
case screen1
case screen2
}
struct MenuView: View {
#Binding var showMenu: Bool
#Binding var selected: SelectedScreen
var body: some View {
HStack {
VStack(alignment: .leading, spacing: 24) {
Button {
selected = .home
showMenu = false
} label: {
Label("Home", systemImage: "rectangle.righthalf.inset.fill.arrow.right")
}
Button {
selected = .screen1
showMenu = false
} label: {
Label("Screen 1", systemImage: "1.circle")
}
Button {
selected = .screen2
showMenu = false
} label: {
Label("Screen 2", systemImage: "2.circle")
}
}
.padding()
.frame(maxHeight: .infinity)
.background(Color(red: 32/255, green: 32/255, blue: 32/255))
Spacer()
}
}
}
struct MainView: View {
var body: some View {
Text("This is Main View")
.font(.largeTitle)
}
}
struct OtherView: View {
let screen: Int
var body: some View {
Text("Other View: Screen \(screen)")
.font(.largeTitle)
}
}
I have the following in problem.
If I try to give a view a color (Color.red for example)
I get the following output:
I can just add .edgesignoressafearea(.top) and the top also gets red. But when I want to add an clickable item, the user won't be able to click it since there still is this invisible bar on the top of the screen. Does Anyone know what my problem is? The problem is in all the tabable views(Timeline, Favorits, Discover, Account). So It must be in either the first code or in tabview (second code) that I send in this post.
When the user clicks on the app first they get this view sending the user to the signin view or the app itself:
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: tabView().navigationBarHidden(true), isActive: $tabview, label: { EmptyView() })
NavigationLink(destination: loginView().navigationBarHidden(true), isActive: $login, label: { EmptyView() })
if tabview == false && login == false {
Text("loading")
.onAppear(perform: checklogin)
}
}
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)
}
}
Then the apps sends them to tabview:
var body: some View {
TabView(selection: $selection) {
Timeline()
.tabItem {
Label("timeline", systemImage: "house")
}
.tag(0)
Favorits()
.tabItem {
Label("favorits", systemImage: "heart")
}
.tag(1)
Discover()
.tabItem {
Label("discover", systemImage: "network")
}
.tag(2)
Account()
.tabItem {
Label("account", systemImage: "person")
}
.tag(3)
}
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)
}
The problem happens on all of this views.
This is the view where I made the screenshot of:
var body: some View {
ZStack {
Color.red
Text("Hello fav!")
}
.navigationBarBackButtonHidden(true)
.navigationBarHidden(true)
}
add .edgesIgnoringSafeArea(.top) and remove your navigation bar if you don't want to be able to get back to your login view anytime.
That's the full code with a login page, now it depends what you want on that login page :
import SwiftUI
struct ContentView: View {
#State var showLoginView: Bool = false
var body: some View {
VStack {
if showLoginView {
MainView()
} else {
Button("Login") {
self.showLoginView = true
}
}
}
}
}
struct MainView: View {
var body: some View {
TabView {
TimeLine()
.tabItem {
Label("timeline", systemImage: "house")
}
Favorits()
.tabItem {
Label("favorits", systemImage: "heart")
}
Discover()
.tabItem {
Label("discover", systemImage: "network")
}
Account()
.tabItem {
Label("account", systemImage: "person")
}
}
}
}
struct TimeLine: View {
var body: some View {
Color.blue
.edgesIgnoringSafeArea(.top)
}
}
struct Favorits: View {
var body: some View {
ZStack {
Color.red
.edgesIgnoringSafeArea(.top)
Text("Hello fav!")
}
}
}
struct Discover: View {
var body: some View {
Color.yellow
.edgesIgnoringSafeArea(.top)
}
}
struct Account: View {
var body: some View {
Color.purple
.edgesIgnoringSafeArea(.top)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
You need to set the navigation Title to "" because your View is embedded in NavigationView
Create a ViewModifier like this and apply it to your VStack
struct HiddenNavBarModifier: ViewModifier {
func body(content: Content) -> some View {
content
.navigationBarTitle("", displayMode: .inline)
.navigationBarHidden(true)
}
}
How can I change the Color from the Button in a Alert and the back Button from NavigationLink? To set .accentColor(.init("someColor")) after the Text from the Alert Button doesn't work. To set .accentColor(.init("someColor")) after navigationLink does not work too. What can I do?
The Alert Button:
The Back Button from NavigationLink:
struct ContentView: View {
#State var showSheet = false
#State var alertShouldBeShown = !UserDefaults.standard.bool(forKey: "£Start")
var body: some View {
Button(action: {
self.showSheet.toggle()
}) {
Text("click me")
//.accentColor(colorScheme == .dark ? Image("") : Image("Info-Icon"))
}.sheet(isPresented: $showSheet) {
SheetView(showSheet: self.$showSheet)
}
.alert(isPresented: $alertShouldBeShown, content: {
Alert(title: Text("Headline"),
message: Text("Text"),
dismissButton: Alert.Button.default(
Text("Ok"), action: {
UserDefaults.standard.set(true, forKey: "Start")
}
)
)
})
}
}
struct SheetView: View {
#Binding var showSheet: Bool
var body: some View {
NavigationView {
DetailView()
.navigationBarTitle(Text("Headline"), displayMode: .inline)
.navigationBarItems(trailing: Button(action: {
self.showSheet = false
}) {
Text("Done")
.bold()
})
}.navigationViewStyle(StackNavigationViewStyle())
}
}
struct DetailView: View {
var body: some View {
List {
HStack {
NavigationLink(destination: DetailViewOne()) {
Text("View 1")
}
}
HStack {
NavigationLink(destination: DetailViewTwo()) {
Text("View 2")
}
}
}
}
}
struct DetailViewOne: View {
var body: some View {
Text("1")
}
}
struct DetailViewTwo: View {
var body: some View {
Text("2")
}
}
You can change the NavigationBar accent color by using accentColor but you need to apply it to the SheetView (the root view of a given environment):
SheetView(showSheet: self.$showSheet)
.accentColor(.red)
Unfortunately SwiftUI doesn't allow much of Alert customisation so far.
However, as Alert is built on top of UIKit components (UIAlertController) this also means you can change the appearance of UIView when contained in UIAlertController.
You can put this code in your #main App init or in the SceneDelegate:
UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor = .red
Is there any way to pop to root view by tapping the Tab Bar like most iOS apps, in SwiftUI?
Here's an example of the expected behavior.
I've tried to programmatically pop views using simultaneousGesture as follow:
import SwiftUI
struct TabbedView: View {
#State var selection = 0
#Environment(\.presentationMode) var presentationMode
var body: some View {
TabView(selection: $selection) {
RootView()
.tabItem {
Image(systemName: "house")
.simultaneousGesture(
TapGesture().onEnded {
self.presentationMode.wrappedValue.dismiss()
print("View popped")
}
)
}.tag(0)
Text("")
.tabItem {
Image(systemName: "line.horizontal.3")
}.tag(1)
}
}
}
struct RootView: View {
var body: some View {
NavigationView {
NavigationLink(destination: SecondView()) {
Text("Go to second view")
}
}
}
}
struct SecondView: View {
var body: some View {
Text("Tapping the house icon should pop back to root view")
}
}
But seems like those gestures were ignored.
Any suggestions or solutions are greatly appreciated
We can use tab bar selection binding to get the selected index. On this binding we can check if the tab is already selected then pop to root for navigation on selection.
struct ContentView: View {
#State var showingDetail = false
#State var selectedIndex:Int = 0
var selectionBinding: Binding<Int> { Binding(
get: {
self.selectedIndex
},
set: {
if $0 == self.selectedIndex && $0 == 0 && showingDetail {
print("Pop to root view for first tab!!")
showingDetail = false
}
self.selectedIndex = $0
}
)}
var body: some View {
TabView(selection:selectionBinding) {
NavigationView {
VStack {
Text("First View")
NavigationLink(destination: DetailView(), isActive: $showingDetail) {
Text("Go to detail")
}
}
}
.tabItem { Text("First") }.tag(0)
Text("Second View")
.tabItem { Text("Second") }.tag(1)
}
}
}
struct DetailView: View {
var body: some View {
Text("Detail")
}
}
I messed around with this for a while and this works great. I combined answers from all over and added some stuff of my own. I'm a beginner at Swift so feel free to make improvements.
Here's a demo.
This view has the NavigationView.
import SwiftUI
struct AuthenticatedView: View {
#StateObject var tabState = TabState()
var body: some View {
TabView(selection: $tabState.selectedTab) {
NavigationView {
NavigationLink(destination: TestView(titleNum: 0), isActive: $tabState.showTabRoots[0]) {
Text("GOTO TestView #1")
.padding()
.foregroundColor(Color.white)
.frame(height:50)
.background(Color.purple)
.cornerRadius(8)
}
.navigationTitle("")
.navigationBarTitleDisplayMode(.inline)
}
.navigationViewStyle(.stack)
.onAppear(perform: {
tabState.lastSelectedTab = TabState.Tab.first
}).tabItem {
Label("First", systemImage: "list.dash")
}.tag(TabState.Tab.first)
NavigationView {
NavigationLink(destination: TestView(titleNum: 0), isActive: $tabState.showTabRoots[1]) {
Text("GOTO TestView #2")
.padding()
.foregroundColor(Color.white)
.frame(height:50)
.background(Color.purple)
.cornerRadius(8)
}.navigationTitle("")
.navigationBarTitleDisplayMode(.inline).navigationBarTitle(Text(""), displayMode: .inline)
}
.navigationViewStyle(.stack)
.onAppear(perform: {
tabState.lastSelectedTab = TabState.Tab.second
}).tabItem {
Label("Second", systemImage: "square.and.pencil")
}.tag(TabState.Tab.second)
}
.onReceive(tabState.$selectedTab) { selection in
if selection == tabState.lastSelectedTab {
tabState.showTabRoots[selection.rawValue] = false
}
}
}
}
struct AuthenticatedView_Previews: PreviewProvider {
static var previews: some View {
AuthenticatedView()
}
}
class TabState: ObservableObject {
enum Tab: Int, CaseIterable {
case first = 0
case second = 1
}
#Published var selectedTab: Tab = .first
#Published var lastSelectedTab: Tab = .first
#Published var showTabRoots = Tab.allCases.map { _ in
false
}
}
This is my child view
import SwiftUI
struct TestView: View {
let titleNum: Int
let title: String
init(titleNum: Int) {
self.titleNum = titleNum
self.title = "TestView #\(titleNum)"
}
var body: some View {
VStack {
Text(title)
NavigationLink(destination: TestView(titleNum: titleNum + 1)) {
Text("Goto View #\(titleNum + 1)")
.padding()
.foregroundColor(Color.white)
.frame(height:50)
.background(Color.purple)
.cornerRadius(8)
}
NavigationLink(destination: TestView(titleNum: titleNum + 100)) {
Text("Goto View #\(titleNum + 100)")
.padding()
.foregroundColor(Color.white)
.frame(height:50)
.background(Color.purple)
.cornerRadius(8)
}
.navigationTitle(title)
.navigationBarTitleDisplayMode(.inline)
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView(titleNum: 0)
}
}
You can achieve this by having the TabView within a NavigationView like so:
struct ContentView: View {
#State var selection = 0
var body: some View {
NavigationView {
TabView(selection: $selection) {
FirstTabView()
.tabItem {
Label("Home", systemImage: "house")
}
.tag(0)
}
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
struct FirstTabView: View {
var body: some View {
NavigationLink("SecondView Link", destination: SecondView())
}
}
struct SecondView: View {
var body: some View {
Text("Second View")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ContentView()
}
}
}