How to set the view on top in ios SwiftUI? - ios

I had tried this code, I have also tried with stacks but not able to align with top .
I just want the view to appear on top with auto layout as like UIKit .
import SwiftUI
struct ItemDetail: View {
let item : MenuItem
var body: some View {
HStack(alignment: .top){
VStack{
Image(item.mainImage)
Text(item.description)
}
.padding(10)
.background(.red)
.navigationTitle(item.name)
}
}
}
struct ItemDetail_Previews: PreviewProvider {
static var previews: some View {
ItemDetail(item: MenuItem.example)
}
}

Swap the HStack for a VStack and add a Spacer() at the end. e.g.:
struct ItemDetail: View {
let item : MenuItem
var body: some View {
VStack{
VStack{
Image(item.mainImage)
Text(item.description)
}
.padding(10)
.background(.red)
.navigationTitle(item.name)
Spacer()
}
}
}

This should do it:
VStack()
{
VStack
{
Image(item.mainImage)
Text(item.description)
}
.padding(10)
.background(.red)
.navigationTitle(item.name)
Spacer()
}

Related

Dismiss Tab View from a Child Navigation View and go back to RootView SwiftUI

My Navigation Flow:
Here, my View A to View G is under one Navigation View.
NavigationView {
ViewA()
}
And from View D & View G I am moving to my TabView H by modal, like this:
Button(action: {
isPresented.toggle()
}, label: {
Text("GO!")
})
.fullScreenCover(isPresented: $isPresented) {
TabbarView()
}
In my Tab View all the views have their own Navigation View, like this:
TabView(selection: $tabbarViewModel.tabSelection) {
NavigationView {
HomeView()
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
Text("Home")
}
}
}.navigationViewStyle(StackNavigationViewStyle())
.tabItem {
Image(systemName: "house")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
Text("Home")
}
.tag(0)
NavigationView {
CartView()
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
Text("Cart")
}
}
}.navigationViewStyle(StackNavigationViewStyle())
.tabItem {
Image(systemName: "cart")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
Text("Cart")
}
.tag(1)
NavigationView {
ProductView()
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
Text("Product")
}
}
}.navigationViewStyle(StackNavigationViewStyle())
.tabItem {
Image(systemName: "seal")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
Text("Product")
}
.tag(2)
NavigationView {
ProfileView()
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
Text("Profile")
}
}
}.navigationViewStyle(StackNavigationViewStyle())
.tabItem {
Image(systemName: "person")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
Text("Profile")
}
.tag(3)
}
.accentColor(Color("AppsDefaultColor"))
Now I want to go back to viewA, say from Home View by pressing the Sign Out button. I tried this, just to see if it takes me back to previous view, but it doesn't work.
struct HomeView: View {
#Environment(\.presentationMode) var presentationMode
var body: some View {
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text("Dismiss")
})
}
}
So how can I dismiss the tabview and go back to my Root view A?
Finally I have managed to achieve this. To roll back to the Root view I used this:
NavigationLink(destination: <#T##_#>, tag: <#T##Hashable#>, selection: <#T##Binding<Hashable?>#>, label: <#T##() -> _#>)
And to dismiss the presented view, I used this:
UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true, completion: nil)
To be honest it's quite simple. All we need to make NavigationLink selection which is selectedItem in this case to nil & dismiss the modal throughout the project. All of these have done inside of a tab bar view model class with the help of #EnvironmentObject
First create the TabbarViewModel: ObservableObject:
import Foundation
import SwiftUI
class TabbarViewModel: ObservableObject {
#Published var tabSelection: Int = 0
#Published var selectedItem: String? = nil
func gotoRootView() {
withAnimation {
UIApplication.shared.windows.first?.rootViewController?.dismiss(animated: true, completion: nil)
selectedItem = nil
}
}
}
Now, let's create the ViewA which is AuthListView:
import SwiftUI
struct CellItem: Identifiable {
var id = UUID()
let title: String
let image: String
let destination: AnyView
}
struct AuthListView: View {
var body: some View {
AuthListContentView()
.navigationBarHidden(true)
}
}
struct AuthListContentView: View {
#State private var cellList: [CellItem] = [
CellItem(title: "Icon", image: "", destination: AnyView(EmptyView())),
CellItem(title: "Phone", image: "Phone", destination: AnyView(PhoneView())),
CellItem(title: "Email", image: "Email", destination: AnyView(SignInView())),
CellItem(title: "Google", image: "Google", destination: AnyView(GoogleView())),
CellItem(title: "Facebook", image: "Facebook", destination: AnyView(FacebookView())),
CellItem(title: "Twitter", image: "Twitter", destination: AnyView(TwitterView()))]
var body: some View {
List(cellList, id: \.id) { item in
if item.title == "Icon" {
IconImageView()
} else {
AuthListCell(cellItem: item)
}
}
}
}
struct IconImageView: View {
var body: some View {
VStack {
Image("firebase")
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 120, height: 120, alignment: .center)
}
.frame(maxWidth: .infinity, minHeight: 120, alignment: .center)
.padding(.top, 50)
.padding(.bottom, 50)
}
}
This is each cell of auth View:
import SwiftUI
struct AuthListCell: View {
var cellItem: CellItem
#EnvironmentObject var tabbarViewModel: TabbarViewModel
var body: some View {
NavigationLink(
destination: cellItem.destination,
tag: cellItem.title,
selection: $tabbarViewModel.selectedItem) {
cell(cellItem: cellItem)
}
}
}
struct cell: View {
var cellItem: CellItem
var body: some View {
HStack(spacing: 15) {
Image(cellItem.image)
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: 28, maxHeight: .infinity, alignment: .center)
Text(cellItem.title)
.foregroundColor(Color("DefaultText"))
.font(.system(size: 17))
Spacer()
}
.padding(.top, 5)
.padding(.bottom, 5)
}
}
Load this view inside of your ContentView under a Navigation View:
struct ContentView: View {
#Environment(\.managedObjectContext) private var viewContext
var body: some View {
NavigationView {
AuthListView()
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
Till now, we can push to ViewB from ViewA. Here, I am only showing the navigation flow for ViewA push> ViewB push> ViewC present> TabView > and then Dismiss TabView from HomeView and go back to root ViewA, cause rest of the other views will follow the same. It also works from a child navigation of any Tab bar views as well. So let's create ViewB(PhoneView) and push toViewC(PINView):
ViewB:
struct PhoneView: View {
var body: some View {
PhoneContentView()
.navigationBarTitle("Phone Number", displayMode: .inline)
}
}
struct PhoneContentView: View {
var body: some View {
NavigationLink(destination: PINView()) {
Text("Go")
}
}
}
ViewC:
struct PINView: View {
var body: some View {
PINContentView()
.navigationBarTitle("PIN", displayMode: .inline)
}
}
struct PINContentView: View {
#State private var isPresented = false
var body: some View {
Button(action: {
isPresented.toggle()
}, label: {
Text("Sign In")
})
.fullScreenCover(isPresented: $isPresented) {
TabbarView()
}
}
}
Till now we have presented the tab view from previous ViewC. This is our tab view:
import SwiftUI
struct TabbarView: View {
#EnvironmentObject var tabbarViewModel: TabbarViewModel
var body: some View {
TabView(selection: $tabbarViewModel.tabSelection) {
NavigationView {
HomeView().navigationBarTitle("Home", displayMode: .inline)
}
.navigationViewStyle(StackNavigationViewStyle())
.tabItem {
Image(systemName: "house")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
Text("Home")
}
.tag(0)
NavigationView {
CartView().navigationBarTitle("Cart", displayMode: .inline)
}
.navigationViewStyle(StackNavigationViewStyle())
.tabItem {
Image(systemName: "cart")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
Text("Cart")
}
.tag(1)
NavigationView {
ProductView().navigationBarTitle("Product", displayMode: .inline)
}
.navigationViewStyle(StackNavigationViewStyle())
.tabItem {
Image("product")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
Text("Product")
}
.tag(2)
NavigationView {
ProfileView().navigationBarTitle("Profile", displayMode: .inline)
}
.navigationViewStyle(StackNavigationViewStyle())
.tabItem {
Image(systemName: "person")
.renderingMode(.template)
.resizable()
.aspectRatio(contentMode: .fit)
Text("Profile")
}
.tag(3)
}
.accentColor(Color("AppsDefaultColor"))
}
}
Now, If I want to dismiss the presented tab view & go back to root view by pressing sign out button from my HomeView, all I have to do is call tabbarViewModel.gotoRootView() like this:
struct HomeView: View {
#EnvironmentObject var tabbarViewModel: TabbarViewModel
var body: some View {
Button(action: {
tabbarViewModel.gotoRootView()
}, label: {
Text("Sign Out")
})
}
}
I can dismiss the tab view and go to the root view from a child view of my HomeView as well. Let's go to a child view from the HomeView:
struct HomeView: View {
var body: some View {
NavigationLink(destination: HomeDetailsView()) {
Text("Go")
}
}
}
This is the HomedetailsView` and by following the same call I can accomplish the same result like this:
struct HomeDetailsView: View {
var body: some View {
HomeDetailsContentView()
.navigationBarTitle("Home Details", displayMode: .inline)
}
}
struct HomeDetailsContentView: View {
#EnvironmentObject var tabbarViewModel: TabbarViewModel
var body: some View {
Button(action: {
tabbarViewModel.gotoRootView()
}, label: {
Text("Dismiss")
})
}
}
By this you can dismiss tab view and go to the root view from any view of your project. :)

SwiftUI change view from first screen to tabview screen

I want to change views once the user taps 'get started' but due to having navigation view in my first view, it is showing back button on my next screen which I don't want. Please see the images attached below.
Code for the first view is below:
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Spacer()
Text("LifePath")
.font(.system(size: 48, weight: .semibold))
.padding(.bottom)
Spacer()
NavigationLink(destination: ViewChanger()) {
Text("Get Started")
.font(.headline)
.navigationBarBackButtonHidden(true)
}
}
.padding()
}
}
}
back button showing on screen 2
First view
Change the location of your navigationBackButtonHidden modifier so that it actually modifies the view that you're going to (and not the NavigationLink label):
struct ContentView: View {
var body: some View {
NavigationView {
VStack {
Spacer()
Text("LifePath")
.font(.system(size: 48, weight: .semibold))
.padding(.bottom)
Spacer()
NavigationLink(destination: ViewChanger()
.navigationBarBackButtonHidden(true) // <-- Here
) {
Text("Get Started")
.font(.headline)
}
}
.padding()
}
}
}
If you want not only the back button to be gone, but the entire header bar, you can use the .navigationBarHidden(true) modifier.
Also, if you run this on iPad at all, you probably want .navigationViewStyle(StackNavigationViewStyle()) added to the outside of your NavigationView
If you use a NavigationLink (in a NavigationView), the view will be pushed. If you want to replace the view, you can do this with an if statement.
For example, this could be implemented like this:
struct ContentView: View {
#State var showSecondView: Bool = false
var body: some View {
if !showSecondView {
NavigationView {
VStack {
Spacer()
Text("LifePath")
.font(.system(size: 48, weight: .semibold))
.padding(.bottom)
Spacer()
Button(action: { showSecondView = true }) {
Text("Get Started")
.font(.headline)
}
}
.padding()
} else {
TabView {
// ...
}
}
}
}

Place text between top and center of the screen

Is there a simple way to place text relatively between the top and center of the screen? With 'simple' I mean preferably without GeometryReader and overt calculations.
I've tried various combinations of VStack, Zstack and Spacer() but to no avail.
Code and screenshot as illustration:
struct ContentView: View {
var body: some View {
Text("Between top and center")
.offset(y: -150)
Text("Center")
}
}
A possible solution is to create two views on each side of the centred text (one hidden):
struct ContentView: View {
var body: some View {
VStack {
Spacer()
Text("Between top and center")
Spacer()
Text("Center")
Spacer()
Text("")
Spacer()
}
}
}
Alternatively, to be fool-proof (in case they change the behaviour of Text("") in the future release):
struct ContentView: View {
var body: some View {
VStack {
Spacer()
Text("Between top and center")
Spacer()
Text("Center")
Spacer()
Text("Between top and center")
.opacity(0)
Spacer()
}
}
}
(If needed, Text("Between top and center") can be extracted as a subview to avoid code duplication.)
As you said:
Spacer() [...] ensure[s] that the empty spaces between the views are equal in size
That's exactly the reason why I recommended to extract Text("Between top and center") as a subview. Then, you can change the font, size etc. of the view in one place only.
The adapted solution is:
struct ContentView: View {
var body: some View {
ZStack {
VStack {
Spacer()
subview
Spacer()
Spacer()
subview
.opacity(0)
Spacer()
}
VStack {
Spacer()
Text("Center")
Spacer()
}
}
}
var subview: some View {
Text("Between top and center")
.font(.caption)
// apply all other modifiers if you want
}
}
Here is possible solution (tested with Xcode 12.1 / iOS 14.1)
struct ContentView: View {
var body: some View {
VStack {
Color.clear.overlay(
Text("Between top and center") // << here !!
)
// Text("Between top and center")
// .frame(maxWidth: .infinity, maxHeight: .infinity) // alternate !!
Text("Center")
Color.clear
}
}
}
Update: added alternate with .frame but it is valid only if there should be the only one Text, whereas in .overlay it is possible to put anything.
Here is another solution using the method of VStack Spacers, I also used a little padding to get you closer to the center.
import SwiftUI
struct ContentView: View {
var body: some View {
VStack {
Text("Top").bold()
.foregroundColor(.blue)
Spacer()
Text("Your desired area")
Spacer()
Text("Middle Text").bold()
.foregroundColor(.blue)
.padding(.bottom, 200)
Spacer()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

SwiftUI Hide TabView bar inside NavigationLink views

I have a TabView and separate NavigationView stacks for every Tab item. It works well but when I open any NavigationLink the TabView bar is still displayed. I'd like it to disappear whenever I click on any NavigationLink.
struct MainView: View {
#State private var tabSelection = 0
var body: some View {
TabView(selection: $tabSelection) {
FirstView()
.tabItem {
Text("1")
}
.tag(0)
SecondView()
.tabItem {
Text("2")
}
.tag(1)
}
}
}
struct FirstView: View {
var body: some View {
NavigationView {
NavigationLink(destination: FirstChildView()) { // How can I open FirstViewChild with the TabView bar hidden?
Text("Go to...")
}
.navigationBarTitle("FirstTitle", displayMode: .inline)
}
}
}
I found a solution to put a TabView inside a NavigationView, so then after I click on a NavigationLink the TabView bar is hidden. But this messes up NavigationBarTitles for Tab items.
struct MainView: View {
#State private var tabSelection = 0
var body: some View {
NavigationView {
TabView(selection: $tabSelection) {
...
}
}
}
}
struct FirstView: View {
var body: some View {
NavigationView {
NavigationLink(destination: FirstChildView()) {
Text("Go to...")
}
.navigationBarTitle("FirstTitle", displayMode: .inline) // This will not work now
}
}
}
With this solution the only way to have different NavigationTabBars per TabView item, is to use nested NavigationViews. Maybe there is a way to implement nested NavigationViews correctly? (As far as I know there should be only one NavigationView in Navigation hierarchy).
How can I hide TabView bar inside NavigationLink views correctly in SwiftUI?
I really enjoyed the solutions posted above, but I don't like the fact that the TabBar is not hiding according to the view transition.
In practice, when you swipe left to navigate back when using tabBar.isHidden, the result is not acceptable.
I decided to give up the native SwiftUI TabView and code my own.
The result is more beautiful in the UI:
Here is the code used to reach this result:
First, define some views:
struct FirstView: View {
var body: some View {
NavigationView {
VStack {
Text("First View")
.font(.headline)
}
.navigationTitle("First title")
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.background(Color.yellow)
}
}
}
struct SecondView: View {
var body: some View {
VStack {
NavigationLink(destination: ThirdView()) {
Text("Second View, tap to navigate")
.font(.headline)
}
}
.navigationTitle("Second title")
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.background(Color.orange)
}
}
struct ThirdView: View {
var body: some View {
VStack {
Text("Third View with tabBar hidden")
.font(.headline)
}
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity, alignment: .center)
.background(Color.red.edgesIgnoringSafeArea(.bottom))
}
}
Then, create the TabBarView (which will be the root view used in your app):
struct TabBarView: View {
enum Tab: Int {
case first, second
}
#State private var selectedTab = Tab.first
var body: some View {
VStack(spacing: 0) {
ZStack {
if selectedTab == .first {
FirstView()
}
else if selectedTab == .second {
NavigationView {
VStack(spacing: 0) {
SecondView()
tabBarView
}
}
}
}
.animation(nil)
if selectedTab != .second {
tabBarView
}
}
}
var tabBarView: some View {
VStack(spacing: 0) {
Divider()
HStack(spacing: 20) {
tabBarItem(.first, title: "First", icon: "hare", selectedIcon: "hare.fill")
tabBarItem(.second, title: "Second", icon: "tortoise", selectedIcon: "tortoise.fill")
}
.padding(.top, 8)
}
.frame(height: 50)
.background(Color.white.edgesIgnoringSafeArea(.all))
}
func tabBarItem(_ tab: Tab, title: String, icon: String, selectedIcon: String) -> some View {
ZStack(alignment: .topTrailing) {
VStack(spacing: 3) {
VStack {
Image(systemName: (selectedTab == tab ? selectedIcon : icon))
.font(.system(size: 24))
.foregroundColor(selectedTab == tab ? .primary : .black)
}
.frame(width: 55, height: 28)
Text(title)
.font(.system(size: 11))
.foregroundColor(selectedTab == tab ? .primary : .black)
}
}
.frame(width: 65, height: 42)
.onTapGesture {
selectedTab = tab
}
}
}
This solution also allows a lot of customization in the TabBar.
You can add some notifications badges, for example.
If we talk about standard TabView, the possible workaround solution can be based on TabBarAccessor from my answer on Programmatically detect Tab Bar or TabView height in SwiftUI
Here is a required modification in tab item holding NavigationView. Tested with Xcode 11.4 / iOS 13.4
struct FirstTabView: View {
#State private var tabBar: UITabBar! = nil
var body: some View {
NavigationView {
NavigationLink(destination:
FirstChildView()
.onAppear { self.tabBar.isHidden = true } // !!
.onDisappear { self.tabBar.isHidden = false } // !!
) {
Text("Go to...")
}
.navigationBarTitle("FirstTitle", displayMode: .inline)
}
.background(TabBarAccessor { tabbar in // << here !!
self.tabBar = tabbar
})
}
}
Note: or course if FirstTabView should be reusable and can be instantiated standalone, then tabBar property inside should be made optional and handle ansbsent tabBar explicitly.
Thanks to another Asperi's answer I was able to find a solution which does not break animations and looks natural.
struct ContentView: View {
#State private var tabSelection = 1
var body: some View {
NavigationView {
TabView(selection: $tabSelection) {
FirstView()
.tabItem {
Text("1")
}
.tag(1)
SecondView()
.tabItem {
Text("2")
}
.tag(2)
}
// global, for all child views
.navigationBarTitle(Text(navigationBarTitle), displayMode: .inline)
.navigationBarHidden(navigationBarHidden)
.navigationBarItems(leading: navigationBarLeadingItems, trailing: navigationBarTrailingItems)
}
}
}
struct FirstView: View {
var body: some View {
NavigationLink(destination: Text("Some detail link")) {
Text("Go to...")
}
}
}
struct SecondView: View {
var body: some View {
Text("We are in the SecondView")
}
}
Compute navigationBarTitle and navigationBarItems dynamically:
private extension ContentView {
var navigationBarTitle: String {
tabSelection == 1 ? "FirstView" : "SecondView"
}
var navigationBarHidden: Bool {
tabSelection == 3
}
#ViewBuilder
var navigationBarLeadingItems: some View {
if tabSelection == 1 {
Text("+")
}
}
#ViewBuilder
var navigationBarTrailingItems: some View {
if tabSelection == 1 {
Text("-")
}
}
}
How about,
struct TabSelectionView: View {
#State private var currentTab: Tab = .Scan
private enum Tab: String {
case Scan, Validate, Settings
}
var body: some View {
TabView(selection: $currentTab){
ScanView()
.tabItem {
Label(Tab.Scan.rawValue, systemImage: "square.and.pencil")
}
.tag(Tab.Scan)
ValidateView()
.tabItem {
Label(Tab.Validate.rawValue, systemImage: "list.dash")
}
.tag(Tab.Validate)
SettingsView()
.tabItem {
Label(Tab.Settings.rawValue, systemImage: "list.dash")
}
.tag(Tab.Settings)
}
.navigationBarTitle(Text(currentTab.rawValue), displayMode: .inline)
}
}
I also faced this problem. I don't want to rewrite, but the solution is in my github. I wrote everything in detail there
https://github.com/BrotskyS/AdvancedNavigationWithTabView
P.S: I have no reputation to write comments. Hikeland's solution is not bad. But you do not save the State of the page. If you have a ScrollView, it will reset to zero every time when you change tab
Also you can create very similar custom navBar for views in TabView
struct CustomNavBarView<Content>: View where Content: View {
var title: String = ""
let content: Content
init(title: String, #ViewBuilder content: () -> Content) {
self.title = title
self.content = content()
}
var body: some View {
content
.safeAreaInset(edge: .top, content: {
HStack{
Spacer()
Text(title)
.fontWeight(.semibold)
Spacer()
}
.padding(.bottom, 10)
.frame(height: 40)
.frame(maxWidth: .infinity)
.background(.ultraThinMaterial)
.overlay {
Divider()
.frame(maxHeight: .infinity, alignment: .bottom)
}
})
}
}
CustomNavBarView(title: "Create ad"){
ZStack{
NavigationLink(destination: SetPinMapView(currentRegion: $vm.region, region: vm.region), isActive: $vm.showFullMap) {
Color.clear
}
Color("Background").ignoresSafeArea()
content
}
}

Adding a TabView makes the Navigation Bar not cover the safe area in SwiftUI

When adding a TabView in my SwiftUI iOS App, the Navigation Bar stops covering up the notch
I've tried creating another file for the TabView implementation ( Modifying SceneDeletage and so on)
Here is a simple code without TabView that makes the Navigation Bar cover the safe area (aka the notch)
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView{
ScrollView{
HStack{
VStack{
ForEach((1...10), id: \.self){_ in
Text("Hello")
.padding(.leading, 20)
}
}
Spacer()
//.padding(.leading, 20)
}
}
.navigationBarTitle("Title Covers Safe Area")
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Here is a code with TabView that makes the Navigation Bar NOT cover up the safe area
import SwiftUI
struct ContentView: View {
var body: some View {
TabView {
NavigationView{
ScrollView{
HStack{
VStack{
ForEach((1...10), id: \.self){_ in
Text("Hello")
}
}
Spacer()
}
.padding(.leading, 20)
}
.navigationBarTitle("Doesn't Cover Safe Area")
}
.tabItem {
Image(systemName: "1.circle")
Text("First")
}.tag(0)
HStack{
Spacer()
VStack{
Spacer()
Text("Second View")
.font(.system(size: 40))
}
}
.tabItem {
Image(systemName: "2.circle")
Text("Second")
}.tag(1)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
You can use method edgesIgnoringSafeArea(_:)
TabView {
...
}
.edgesIgnoringSafeArea(.top)

Resources