I am working with NavigationView in SwiftUI and having an issue with it extending fully to the bottom of the screen.
I created a simple List in and this works fine. However, when I put it in a NavigationView, it creates a gray area at the bottom. I've tried adjusting the frame and a number of other things to no avail. I've never seen this before. Any help would be appreciated.
struct ListingView: View {
var body: some View {
List(0..<5) { item in
Text("Test")
}
}
}
struct ListingView: View {
var body: some View {
NavigationView {
List(0..<5) { item in
Text("Test")
}
}
}
}
struct ContentView: View {
// PacificBlue Background Set Up.
init() {
UITabBar.appearance().isTranslucent = false
UITabBar.appearance().barTintColor = UIColor(Color.pacificBlue)
}
// MARK: View
var body: some View {
TabView {
SeafoodListView()
.tabItem {
Image(systemName: "line.diagonal.arrow")
Text("Market")
}.tag(0) // SeafoodMarketView
ListingView()
.tabItem {
Image(systemName: "list.bullet.rectangle")
Text("Listings")
}.tag(1) // ListingView
RequestView()
.tabItem {
Image(systemName: "megaphone")
Text("Requests")
}.tag(2) // RequestView
MessengerView()
.tabItem {
Image(systemName: "ellipsis.bubble")
Text("Messenger")
}.tag(3) // MessengerView
AccountView()
.tabItem {
Image(systemName: "person")
Text("Account")
}.tag(4) // AccountView
} // TabView
.accentColor(.white)
}
}
// MARK: Preview
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
This is due to hack with appearance...
init() {
// UITabBar.appearance().isTranslucent = false // remove this line !!!
UITabBar.appearance().barTintColor = UIColor(Color.pacificBlue)
}
Alternate: replace entire appearance with configured opaque background
init() {
let newAppearance = UITabBarAppearance()
newAppearance.configureWithOpaqueBackground()
newAppearance.backgroundColor = UIColor(Color.pacificBlue)
UITabBar.appearance().standardAppearance = newAppearance
}
Related
Xcode RC 14.1
The first tab is generated twice. The first one works, the second brings up a blank screen. This has been reported elsewhere on SO and people suggest removing Spacer()s but this made no difference.
The code below has two variants, one with a enum for the tag as opposed to an integer but they both misbehave identically. (Not sure why all the code hasn't ended up grey below?)
import SwiftUI
struct MenuView: View {
private enum Tab: Hashable {
case location
case calculate
case install
case results
case about
}
// #State private var tabBarSelected: Tab = .location
#State private var selectedTab = 0
var body: some View {
VStack {
TabView(selection: $selectedTab) {
LocationView()
// .tag(Tab.location)
.tag(0)
.tabItem {
Text("Location")
Image(systemName: "globe.europe.africa")
}
CalculateView()
// .tag(Tab.calculate)
.tag(1)
.tabItem {
Text("Calculate")
Image(systemName: "apps.ipad")
}
InstallView()
// .tag(Tab.install)
.tag(2)
.tabItem {
Text("Install")
Image(systemName: "window.ceiling.closed")
}
ResultsView()
.tag(3)
// .tag(Tab.results)
.tabItem {
Text("Results")
Image(systemName: "sun.max.fill")
}
AboutView()
.tag(4)
// .tag(Tab.about)
.tabItem {
Text("About")
Image(systemName: "gear")
}
} // TabView
.accentColor(.yellow) //Active tab color
} // VStack
} // body
init() {
UITabBar.appearance().barTintColor = UIColor.systemGray //TabBar color
UITabBar.appearance().unselectedItemTintColor = UIColor.systemGray2
UITabBar.appearance().isOpaque = false
}
}
struct MenuView_Previews: PreviewProvider {
static var previews: some View {
MenuView()
}
}
You need to wrap your content in a VStack, kindly check your code in LocationView().
Instead of this:
var body: some View {
Text("Hi")
Text("welcome")
}
Use the code below:
var body: some View {
VStack {
Text("Hi")
Text("welcome")
}
}
I have the following code
enum Tab {
case accounts, lootbox
}
struct ContentView: View {
#State private var currentTab:Tab = .lootbox
var body: some View {
TabView(selection: $currentTab){
AccountView()
.tabItem {
Label("Accounts", systemImage: "person.crop.circle")
}
.tag(Tab.accounts)
Lootbox()
.tabItem {
Label("Lootbox", systemImage: "shippingbox")
}
.tag(Tab.lootbox)
}
.tabViewStyle(.page)
}
}
struct AccountView: View {
var body: some View {
NavigationView{
VStack{
Text("AccountView")
Spacer()
.navigationTitle("Lootbox")
}
}
.navigationViewStyle(.stack)
}
}
struct Lootbox: View {
var body: some View {
NavigationView{
VStack{
Text("Lootbox")
Spacer()
}
.navigationTitle("Lootbox")
}
.navigationViewStyle(.stack)
}
}
The VStackhides behind the navigation view title. After swiping right and left, it is as expected. Why is that? Or is this a bug of SwiftUI?
Before swipe left and right:
After (how it should be):
I am using TabView in swiftui. I want navigate child view from tabview tabItem. When I navigate from taview to childview, it shows tabview in bottom. Here is the image.. that click login goes to Myview page. But in Myview, Tabview is not hiding
Here is my code..
Tabview
struct WelcomeView: View {
var body: some View {
TabView {
HomeView()
.tabItem {
Image("home_icon")
Text("Home")
}
.tag(0)
NotificationView()
.tabItem {
Image("notification_icon")
Text("Notification")
}.tag(1)
AccountView()
.tabItem {
Image("account_icon")
Text("Account")
}.tag(2)
SettingView()
.tabItem {
Image("settings_icon")
Text("Setting")
}.tag(3)
}
}
}
In SettingView tabItem:
struct SettingView: View {
#State private var isActive = false
var body: some View {
NavigationView {
VStack(alignment: .leading) {
VStack {
Button(action: {
isActive = true
}) {
Text("Login")
}
NavigationLink("", destination: MyView(), isActive: $isActive)
}
}
}
}
}
MyView:
struct MyView: View {
var body: some View {
ZStack{
Text("Hello My View")
}.navigationBarHidden(true)
.navigationBarTitleDisplayMode(.inline)
}
}
When I click login Button in SettingView tabItem, It goes to MyView page. But in MyView page tabview is not hide.
How to hide tabview from MyView page?
To hide the tab we can add a Bool that will take care of showing the view or not. Then by using #Binding we can pass it to the other child views, whatever changes you make down the chain will affect all the views.
struct WelcomeView: View {
#State var isTabViewShown = true
var body: some View {
TabView {
if isTabViewShown {
HomeView()
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
.tag(0)
NotificationView()
.tabItem {
Image(systemName: "envelope.open.fill")
Text("Notification")
}.tag(1)
AccountView()
.tabItem {
Image(systemName: "person.crop.circle")
Text("Account")
}.tag(2)
SettingView(isTabViewShown: $isTabViewShown)
.tabItem {
Image(systemName: "gearshape")
Text("Setting")
}.tag(3)
}
}
}
}
struct MyView: View {
#Binding var isTabViewShown: Bool
var body: some View {
ZStack{
Text("Hello My View")
}
.navigationBarHidden(false)
.navigationBarTitleDisplayMode(.inline)
.onAppear {
isTabViewShown = false
}
}
}
struct SettingView: View {
#State private var isActive = false
#Binding var isTabViewShown: Bool
var body: some View {
NavigationView {
VStack(alignment: .leading) {
VStack {
Button(action: {
isActive = true
}) {
Text("Login")
}
NavigationLink("", destination: MyView(isTabViewShown: $isTabViewShown), isActive: $isActive)
//Here is a button if you want to show it again
Button(action: {
isTabViewShown.toggle()
//You can also use this is you don't want to use a toggle
// isTabViewShown = true
}) {
Text("Show again")
}
}
}
}
}
}
struct HomeView: View {
var body: some View {
Text("Home View")
}
}
struct NotificationView: View {
var body: some View {
Text("Notification View")
}
}
struct AccountView: View {
var body: some View {
Text("Account View")
}
}
I'm using Navigation View inside TabView and the problem is that if I an on Tab A and with NavigationView I open other Views, when changing from tab A to B and after a while I came back to tab A I dosen't reload tab A from beginning but it show the last View open with NavitagionLink. The problem is that in each View I'm getting data from a DB and because of that if shows an empty view.
My ContentView looks like this:
struct ContentView: View {
#ObservedObject var appState = AppState()
#State var currentTab : Tab
var body: some View {
TabView(selection: $appState.currentTab) {
NavigationView {
HomeView(appState: appState)
}
.tabItem {
if appState.currentTab == .home {
Image(systemName: "house.fill")
} else {
Image(systemName: "house")
}
Text(LocalizedStringKey("HomeTabMenu"))
}.tag(Tab.home)
NavigationView {
SearchView()
}
.tabItem {
if appState.currentTab == .search {
Image(systemName: "magnifyingglass.circle.fill")
} else {
Image(systemName: "magnifyingglass")
}
Text(LocalizedStringKey("SearchTabMenu"))
}.tag(Tab.search)
NavigationView {
AddItemView(appState: appState)
}
.tabItem {
if appState.currentTab == .add {
Image(systemName: "plus.circle.fill")
} else {
Image(systemName: "plus.circle")
}
Text(LocalizedStringKey("SellTabMenu"))
}.tag(Tab.add)
NavigationView {
ShoppingCartFavoritesView()
}
.tabItem {
if appState.currentTab == .favorites {
Image(systemName: "cart.fill")
} else {
Image(systemName: "cart")
}
Text(LocalizedStringKey("CartTabMenu"))
}.tag(Tab.favorites)
NavigationView {
ProfileView(appState: appState)
}
.tabItem {
if appState.currentTab == .profile {
Image(systemName: "person.fill")
} else {
Image(systemName: "person")
}
Text(LocalizedStringKey("ProfileTabMenu"))
}.tag(Tab.profile)
}//End TabView
.accentColor(Color("ColorMainDark"))
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(currentTab: Tab.home)
}
}
class AppState: ObservableObject {
#Published var currentTab : Tab = .home
}
enum Tab {
case home, search, add, favorites, profile
}
And if I open SearchView()
struct SearchView: View {
var body: some View {
NavigationLink(destination: View_2(id: "ABC")){
Text("ABC")
}
}
}
struct View_2: View {
#ObservedObject var performSearchProducts = PerformSearchInProducts()
var id : String
var body: some View {
ScollView {
ForEach(performSearchProducts.products) { product in
Text(product.name)
}
}.onAppear(perform: {
self.performSearchProducts.searchSubCategory(id: id)
})
}
}
If in SearchView I'm on View_2() and the I open another Tab, when I come back to tab SearchView it doesn't show the SearchView(), but it remains on View_2() with the back button in navigation bar.
How can I make to show SearchView() and not keep the state of NavigationLink?
It's the default behavior. Attach id to TabView.
}//End TabView
.accentColor(Color("ColorMainDark"))
.id(appState.currentTab) //<--Here
I need do some refresh on some view after networking request completion, but my tab bar auto switched to first tabview after refreshing the page, here is my code:
//tab view
struct PricesView: View {
#ObservedObject var netWorkManager = NetworkManager.shareInstance
var body: some View {
if netWorkManager.dataList.isEmpty {
LoadingView().onAppear(perform: netWorkManager.fetchPricesData)
} else {
Text("Prices").foregroundColor(.red)
}
}
}
...
//main view
struct ContentView: View {
var body: some View {
TabView {
HomeView().tabItem {
Image(systemName: "house.fill")
Text("home")
}
AlertsView().tabItem {
Image(systemName: "flag.fill")
Text("alerts")
}
LinksView().tabItem {
Image(systemName: "link.icloud")
Text("link")
}
PricesView().tabItem {
Image(systemName: "bitcoinsign.circle")
Text("prices")
}
}
}
}
how can I avoid this?
Use selection and tag.
struct ContentView: View {
#State var selection = 0 // <- Here declare selection
var body: some View {
TabView(selection: $selection) { // <- Use selection here
HomeView().tabItem {
Image(systemName: "house.fill")
Text("home")
}.tag(0) // <- Add tag
AlertsView().tabItem {
Image(systemName: "flag.fill")
Text("alerts")
}.tag(1) // <- Add tag
LinksView().tabItem {
Image(systemName: "link.icloud")
Text("link")
}.tag(2) // <- Add tag
PricesView().tabItem {
Image(systemName: "bitcoinsign.circle")
Text("prices")
}.tag(3) // <- Add tag
}
}
}