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
}
}
}
Related
I am new to SwiftUI and have run into a little challenge. Whenever I go from my Home view to a sub-view and then back to the Home view, I am seeing extra space created in the Navigation view (see linked GIF). I was wondering if anyone had any advice - thanks in advance!
Here is the Home Screen:
struct Home: View {
#State private var view2 = false
var body: some View {
NavigationView {
VStack {
Text("Home View!")
.padding()
NavigationLink(destination: View2(), isActive: $view2) { }
Button {
self.view2 = true
} label: {
Text("Go to next view")
}
}
.navigationTitle("Home")
}
} }
Here is the sub-new (View2):
struct View2: View {
#State private var home = false
var body: some View {
VStack {
Text("This is View 2")
.padding()
NavigationLink(destination: Home().navigationBarBackButtonHidden(true), isActive: $home) { }
Button {
self.home = true
} label: {
Text("Go to Home view")
}
}
.navigationTitle("View 1")
} }
Link to GIF:
Visual GIF of the issue
Every time you push a new Home via a NavigationLink, you're adding another NavigationView to the hierarchy, since Home has a NavigationView in it.
To avoid that, you could separate the NavigationView out and instead link to View:
struct Home: View {
var body: some View {
NavigationView {
View1() //<-- Here
}
}
}
struct View1 : View {
#State private var view2 = false
var body: some View {
VStack {
Text("Home View!")
.padding()
NavigationLink(destination: View2(), isActive: $view2) { }
Button {
self.view2 = true
} label: {
Text("Go to next view")
}
}
.navigationTitle("Home")
}
}
struct View2: View {
#State private var home = false
var body: some View {
VStack {
Text("This is View 2")
.padding()
NavigationLink(destination: View1() //<-- Here
.navigationBarBackButtonHidden(true), isActive: $home) { }
Button {
self.home = true
} label: {
Text("Go to Home view")
}
}
.navigationTitle("View 2")
}
}
That being said, I'm a little skeptical of the strategy here. It seems like instead of pushing a new View1, you might just want to be going back to the existing one. In that case, your code could just look like this:
struct Home: View {
var body: some View {
NavigationView {
View1()
}
}
}
struct View1 : View {
#State private var view2 = false
var body: some View {
VStack {
Text("Home View!")
.padding()
NavigationLink(destination: View2(), isActive: $view2) { }
Button {
self.view2 = true
} label: {
Text("Go to next view")
}
}
.navigationTitle("Home")
}
}
struct View2: View {
#Environment(\.presentationMode) var presentationMode
var body: some View {
VStack {
Text("This is View 2")
.padding()
Button {
presentationMode.wrappedValue.dismiss()
} label: {
Text("Go to Home view")
}
}
.navigationTitle("View 2")
}
}
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 created a TabView with 4 items but with iOS 13.x only the first view is displayed correctly.
When I click on another item's icon, the view is not shown correctly but the app only shows a white view. If I run the app on iOS > 14 I can correctly view all the views.
TabView implementation:
struct ContentView: View {
private enum Tab: Hashable {
case discovery
case qrcode
case devices
case settings
}
#State private var selectedTab: Tab = .discovery
var body: some View {
NavigationView {
TabView(selection: $selectedTab) {
DiscoveryView()
.tabItem {
VStack {
Image(systemName: "lock.rotation.open")
Text("Discovery")
}
}
.tag(0)
QrCodeView()
.tabItem {
VStack {
Image(systemName: "qrcode.viewfinder")
Text("QrCode")
}
}
.tag(1)
DevicesView()
.tabItem {
VStack {
Image(systemName: "qrcode.viewfinder")
Text("My devices")
}
}
.tag(2)
SettingsView()
.tabItem {
VStack {
Image(systemName: "gear")
Text("Settings")
}
}
.tag(3)
}
}
}
Implementation of one of the views:
struct QrCodeView: View {
var body: some View {
Text("QrCode")
}
}
Where am I doing wrong?
It might be a reason of selection... selection and tag types should be the same, so try
#State private var selectedTab: Tab = .discovery
var body: some View {
NavigationView {
TabView(selection: $selectedTab) {
DiscoveryView()
.tabItem {
VStack {
Image(systemName: "lock.rotation.open")
Text("Discovery")
}
}
.tag(.discovery) // << here !!
QrCodeView()
.tabItem {
VStack {
Image(systemName: "qrcode.viewfinder")
Text("QrCode")
}
}
.tag(.qrcode) // << here !!
// ... others the same
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()
}
}
I can navigate to next screen by using NavigationButton (push) or present with PresentationButton (present) but i want to push when i tap on Buttton()
Button(action: {
// move to next screen
}) {
Text("See More")
}
is there a way to do it?
You can do using NavigationLink
Note: Please try in real device. in simulator sometimes not work properly.
struct MasterView: View {
#State var selection: Int? = nil
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DetailsView(), tag: 1, selection: $selection) {
Button("Press me") {
self.selection = 1
}
}
}
}
}
}
struct DetailsView: View {
#Environment(\.presentationMode) var presentation
var body: some View {
Group {
Button("Go Back") {
self.presentation.wrappedValue.dismiss()
}
}
}
}
As you can see to display the new view, add the NavigationLink with isActive: $pushView using <.hidden()> to hide the navigation "arrow".
Next add Text("See More") with tapGesture to make the text respond to taps. The variable pushView will change (false => true) when you click "See More" text.
import SwiftUI
struct ContentView: View {
#State var pushView = false
var body: some View {
NavigationView {
List {
HStack{
Text("test")
Spacer()
NavigationLink(destination: NewView(), isActive: $pushView) {
Text("")
}.hidden()
.navigationBarTitle(self.pushView ? "New view" : "default view")
Text("See More")
.padding(.trailing)
.foregroundColor(Color.blue)
.onTapGesture {
self.pushView.toggle()
}
}
}
}
}
}
struct NewView: View {
var body: some View {
Text("New View")
}
}
ContentView picture
NewView picture
To tap on button and navigate to next screen,You can use NavigationLink like below
NavigationView{
NavigationLink(destination: SecondView()) {
Text("Login")
.padding(.all, 5)
.frame(minWidth: 0, maxWidth: .infinity,maxHeight: 45, alignment: .center)
.foregroundColor(Color.white)
}
}
You can use NavigationLink to implement this:
struct DetailsView: View {
var body: some View {
VStack {
Text("Hello world")
}
}
}
struct ContentView: View {
#State var selection: Int? = nil
var body: some View {
NavigationView {
VStack {
NavigationLink(destination: DetailsView(), tag: 1, selection: $selection) {
Button("Press me") {
self.selection = 1
}
}
}
}
}
}