I am trying to create a tabbed application in Swift using Swift UI. I am using #ObservedObject to store the current view name that should be rendered.
I am trying to change the background color of the UI Tab Bar however every time I add the init to override the method begins chucking errors such as "Argument passed to call that takes no arguments".
I have attached a snippet of the controller code below. Any help to resolve this issue is much appreciated.
import SwiftUI
struct ContentView: View {
#State private var selection = 0
#ObservedObject var coreRouter: CoreRouter
init() {
UITabBar.appearance().backgroundColor = UIColor.blue
}
var body: some View {
TabView(selection: $selection){
Text("First Screen")
.font(.title)
.tabItem {
VStack {
Image(systemName: "house")
Text("Home")
}
}
.tag(0)
Text("Second View")
.font(.title)
.tabItem {
VStack {
Image("calendar")
Text("New Items")
}
}
.tag(1)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(coreRouter: CoreRouter())
}
}
Since your ContentView has a coreRouter property, your init needs to accept a value to assign to that property;
struct ContentView: View {
#State private var selection = 0
#ObservedObject var coreRouter: CoreRouter
init(coreRouter: CoreRouter) {
self.coreRouter = coreRouter
UITabBar.appearance().backgroundColor = UIColor.blue
}
}
try this:
(i had to create a dummy class, because you did not provide the code for corerouter)
class CoreRouter : ObservableObject {
#Published var a = false
}
struct ContentView: View {
#State private var selection = 0
#ObservedObject var coreRouter: CoreRouter
init() {
coreRouter = CoreRouter()
UITabBar.appearance().backgroundColor = UIColor.blue
}
var body: some View {
TabView(selection: $selection){
Text("First Screen")
.font(.title)
.tabItem {
VStack {
Image(systemName: "house")
Text("Home")
}
}
.tag(0)
Text("Second View")
.font(.title)
.tabItem {
VStack {
Image("calendar")
Text("New Items")
}
}
.tag(1)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Related
I have the following files and I don't know why the navigation bar is not showing.
In the first file I am using NavigationView before ContentView().
File 1:
import SwiftUI
#main
struct TwitterCloneApp: App {
var body: some Scene {
WindowGroup {
NavigationView{
ContentView()
}
}
}
}
In second file I am using MainTabView(), but there is no navigation bar space.
File 2
import SwiftUI
struct ContentView: View {
#State private var showMenu = false
var body: some View {
ZStack(alignment: .topLeading){
MainTabView()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Here it is the MainTabView.
File 3:
import SwiftUI
struct MainTabView: View {
#State private var selectedIndex: Int = 0
var body: some View {
TabView(selection: $selectedIndex){
FeedView()
.onTapGesture {
self.selectedIndex = 0
}
.tabItem{
Image(systemName: "house")
}.tag(0)
ExploreView()
.onTapGesture {
self.selectedIndex = 1
}
.tabItem{
Image(systemName: "magnifyingglass")
}.tag(1)
NotificationsView()
.onTapGesture {
self.selectedIndex = 2
}
.tabItem{
Image(systemName: "bell")
}.tag(2)
MessagesView()
.onTapGesture {
self.selectedIndex = 3
}
.tabItem{
Image(systemName: "envelope")
}.tag(3)
}
}
}
struct MainTabView_Previews: PreviewProvider {
static var previews: some View {
MainTabView()
}
}
There is no space for the navigation bar.
There are several things wrong with the code you've posted:
Each sub-view within a TabView should have its own NavigationView.
There shouldn't be a NavigationView at the top level
Each top-level view within a NavigationView should have a .navigationTitle
The tapGesture isn't needed to switch between tabs
so you should end up with
struct TwitterCloneApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
and
struct MainTabView: View {
#State private var selectedIndex: Int = 0
var body: some View {
TabView(selection: $selectedIndex){
NavigationView {
FeedView()
.navigationTitle("Feed")
}
.tabItem{
Image(systemName: "house")
}.tag(0)
NavigationView {
ExploreView()
.navigationTitle("Explore")
}
.tabItem{
Image(systemName: "magnifyingglass")
}.tag(1)
NavigationView {
NotificationsView()
.navigationTitle("Notifications")
}
.tabItem{
Image(systemName: "bell")
}.tag(2)
NavigationView {
MessagesView()
.navigationTitle("Messages")
}
.tabItem{
Image(systemName: "envelope")
}.tag(3)
}
}
}
When i am Switching the Tab in Swiftui Every Time new View is showing and my previous View was Vanished.I have Tried Userdefaults also but not working.
import SwiftUI
struct HomeView: View {
#State var selectedTabs = "house"
var body: some View {
ZStack(alignment: .bottom) {
Color("LightTabColor")
.edgesIgnoringSafeArea(.all)
VStack{
CardView(selectedTab: selectedTabs)
CustomTabBar(selectedTab: $selectedTabs)
.padding(.bottom)
}
}.onAppear {
let selectedTab = UserDefaults.standard.string(forKey: "selectedTabs")
if let selectedTab = selectedTab {
self.selectedTabs = selectedTab
}
}.onDisappear {
UserDefaults.standard.set(self.selectedTabs, forKey: "selectedTabs")
}
}
}
struct CardView: View {
var selectedTab: String
var body: some View {
ZStack{
Color("LightTabColor")
.cornerRadius(25)
.frame(maxWidth: .infinity,maxHeight: .infinity)
.padding(10)
.shadow(radius: 30)
VStack {
// Show the appropriate view based on the selected tab
switch selectedTab {
case "gear.circle":
NewAI()
case "house":
ImageAI()
case "message":
ChatAI()
default:
ImageAI()
}
Spacer()
}
.padding(.leading,10)
.padding(.bottom,10)
}
}
}
struct HomeView_Previews: PreviewProvider {
static var previews: some View {
HomeView()
}
}
When starting my app on iPadOS, there is a blank view/screen on the right side, so I need a solution to force the app to choose or to lunch with the firstDetailsView().
If there is no solution for this problem, how can I add a Text() View on the right side which tells the user something like that -> no DetailView is selected
Here is the sourcecode
ContentView.swift
import SwiftUI
struct ContentView: View {
var body: some View {
TabView {
HomeView()
.tabItem {
Image(systemName: "house.fill")
Text("Home")
}
SettingsView()
.tabItem {
Image(systemName: "gear.circle")
Text("Settings")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
SettingsView.swift
import SwiftUI
struct SettingsView: View {
var body: some View {
Text("Settings")
}
}
struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
SettingsView()
}
}
HomeView.swift
import SwiftUI
struct HomeView: View {
var body: some View {
NavigationView {
ScrollView {
VStack (spacing: -15) {
NavigationLink(destination: firstDetailsView()) {
card(symbol: "1.square", color: Color.orange)
}
NavigationLink(destination: secondDetailsView()) {
card(symbol: "2.square", color: Color.green)
}
NavigationLink(destination: thirdDetailsView()) {
card(symbol: "3.square", color: Color.purple)
}
}
}
.navigationTitle("Title")
}
}
}
struct card: View {
var symbol: String
var color: Color
var body: some View {
HStack {
Text("Link to DetailView")
Image(systemName: symbol)
}
.frame(maxWidth: .infinity, minHeight: 100)
.bold()
.foregroundColor(Color.white)
.background(color)
.padding()
}
}
struct HomeView_Previews: PreviewProvider {
static var previews: some View {
HomeView()
}
}
firstDetailsView.swift
import SwiftUI
struct firstDetailsView: View {
var body: some View {
ZStack {
Color.orange
.ignoresSafeArea()
Text("firstDetailsView!")
}
}
}
struct firstDetailsView_Previews: PreviewProvider {
static var previews: some View {
firstDetailsView()
}
}
secondDetailsView.swift
struct secondDetailsView: View {
var body: some View {
ZStack {
Color.green
.ignoresSafeArea()
Text("secondDetailsView!")
}
}
}
struct secondDetailsView_Previews: PreviewProvider {
static var previews: some View {
secondDetailsView()
}
}
On view with navigation view
NavigationLink(destination: FruitySortedListView(shake: shake), isActive: $showingFruity) { EmptyView() }
On view shown in picture:
.navigationTitle("Navigation Title")
IMAGE: You can see that there is a lot of extra space
Consider this example this works perfectly without the extra space as in the Image.
import SwiftUI
struct ContentView: View {
#State var isActive = true
var body: some View {
NavigationView {
NavigationLink(destination: EmptyView(), isActive: $isActive) {
VStack {
Text("Hi")
Spacer()
}
.background(Color.red)
}
.navigationTitle("Navigation Title")
}
}
}
struct EmptyView: View {
var body: some View {
VStack {
Text("navigation")
Spacer()
}
.background(Color.red)
.navigationTitle("EmptyView")
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I´m trying to programmatically change the current view to other, but isActive attribute from NavigationLink is not working, I guess that I´m forgeting something.
struct MainView: View {
#State public var pushActive = true
var body: some View {
NavigationView{
Text("hello")
NavigationLink(destination: ContentView(), isActive: $pushActive) {
Text("")
}.hidden()
}.onAppear{
self.pushActive = true
}
}
}
This view always show "hello" instead of redirect to ContentView
I solved the problem, The error was put the Text("hello").
The answer is simple:
NavigationView{
if(pushActive){
NavigationLink(destination: ContentView(), isActive: $pushActive) {
Text("")
}.hidden()
}else{
Text("hello")
}
NavigationView accepts only the first child, that's why it wasn't working. Try this:
struct MainView: View {
#State public var pushActive = true
var body: some View {
NavigationView {
VStack {
Text("hello")
NavigationLink(destination: ContentView(), isActive: $pushActive) {
Text("")
}.hidden()
}
}.onAppear {
self.pushActive = true
}
}
}