How come my NavigationLink won't work when clicked? - swift

I am trying to make it so that when I click the icon, the "scoreView()" is opened. When I click it, nothing works right now. Here is the code:
HStack {
Image(systemName: "arrow.counterclockwise")
NavigationLink(destination: scoreView(scoreTracker: $scoreTracker)) {
Spacer()
Image(systemName: "list.bullet")
}
}
Does it have something to do with the fact that I don't have a navigationView? I'm new to this and experimenting so I'm not very clear on it.
EDIT:
I have added a NavigationView, yet the NavigationLink covers half the screen, and when clicked, the view is only changed in that square.
Before clicking the NavigationLink
After clicking the NavigationLink
HStack {
Image(systemName: "arrow.counterclockwise")
NavigationView {
NavigationLink(destination: scoreView(scoreTracker: $scoreTracker)) {
Image(systemName: "list.bullet")
}
}
}

Does it have something to do with the fact that I don't have a navigationView?
Yes. According to the documentation:
Users click or tap a navigation link to present a view inside a NavigationView.
It will only work inside a NavigationView. If you're not using one, consider sheet or fullScreenCover instead. Or, make your own overlay with a ZStack.
Example NavigationView usage:
struct ContentView: View {
var body: some View {
NavigationView { /// directly inside `var body: some View`
VStack { /// if you have multiple views, make sure to put them in a `VStack` or similar
Text("Some text")
/// `ScoreView` should be capitalized
NavigationLink(destination: ScoreView(scoreTracker: $scoreTracker)) {
Image(systemName: "list.bullet")
}
}
}
}
}

Related

SwiftUI: List inside TabView inside NavigationView breaks animation

I want to have a TabView inside a NavigationView. The reason is that I am showing a List inside the TabView. When a user taps on an item in the list, the list uses a NavigationLink to show a detailed screen.
The problem is that the navigationBarTitle is now broken. It does not animate when the user scrolls through the items (sometimes). I don't want to wrap my NavigationView inside the TabView, since that will always show the TabView. I don't want it.
This is the reproduction code. If you run this in the simulator, the animation will break when switch a few times between the tabs and you scroll through the list. You will see that the navigation bar will remain where it is, without the animation.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationView {
TabView {
TestView()
.tabItem {
Image(systemName: "person.3")
}
TestView()
.tabItem {
Image(systemName: "person.2")
}
}
.navigationTitle("Test")
.navigationViewStyle(.stack)
}
}
}
struct TestView: View {
var body: some View {
List {
Text("test")
}
.listStyle(.plain)
}
}

SwiftUI Button cannot be clicked on its whole area

I built a custom Button.
My problem is, that it can be only clicked on the Text Elements not on the whole area of the Button.
What's going wrong, how can I solve this?
struct MyButton: View {
var body: some View
{ Button( action:{ print("pressed") })
{ HStack {
VStack(alignment: .leading){
Text("Tomorrow").font(.caption)
Text("23.5.22 KW 23")
}
Spacer()
}
}
.padding([.horizontal],4.0)
.padding([.vertical],2.0)
.background(RoundedRectangle(cornerRadius: 5).fill(Color.red))
.buttonStyle(PlainButtonStyle())
.padding([.horizontal],8.0)
}
}
By default, only the parts of the view that actually render something are tappable. You need to add a .contentShape(Rectangle()) modifier to your Button to make the entire area interactive.

Add Padding to TabView Page Indicator

I have a view that is a TabView with the style PageTabViewStyle(indexDisplayMode: .always which looks great for my use case however the page indicator is bumping right up to the safe area near the bottom of the screen and it looks bad. I'd like to move the page indicator up to some n value. here's a sample of my view to reproducing it. If this view were built on any device without a Home Button, it will ride on top of the home indicator line.
var body: some View {
ZStack {
TabView(selection: $homeVM.selectedPageIndex) {
// Any number of views here.
}
.frame(width: UIScreen.main.bounds.width)
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .always))
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .never))
}.edgesIgnoringSafeArea(.all)
}
I attempted to add the padding to the ZStack, which does work but then my TabView is cut off on the bottom, which means my cells disappear prematurely.
Here's an image for what I'm trying to fix. Notice the page indicator sits on the home bar indicator. I need the indicators pushed up, without pushing up the background ScrollView
Update #1
This view is being presented by a base view that I use to handle my navigation stack. The view is as follows. The important thing to note here is the .ignoresSafeArea() that I have on this view. I did that because it's a containing view for my eventual TabView to be presented from. Interestingly if I remove this modifier the indicators move up to a more manageable position, but then my form becomes clipped at the top and bottom of the device when scrolling, and that's not ideal.
struct BaseLaunchView: View {
#StateObject var baseNavVM = BaseLaunchViewModel()
#State var shouldLogin = false
#State var shouldRegister = false
var body: some View {
VStack {
switch baseNavVM.loggedIn {
case true:
HomeView()
default:
NavigationView {
VStack{
Spacer()
VStack(spacing: 30) {
VStack {
Text("Stello")
.font(Fonts.title)
Text("Life Groups")
.font(Fonts.body)
}
StelloDivider()
Text("Connect with like minded people, to fellowship and find your home.")
.font(Fonts.subheading)
.multilineTextAlignment(.center)
}
Spacer()
NavigationLink(destination: RegisterOptionsView(isLoggingIn: true), isActive: $shouldLogin) {
Button(action: {
shouldLogin.toggle()
}, label: {
Text("Login")
.font(Fonts.button)
}).buttonStyle(StelloFillButtonStyle())
}
NavigationLink(destination: RegisterOptionsView(isLoggingIn: false), isActive: $shouldRegister) {
Button(action: {
shouldRegister.toggle()
}, label: {
Text("Register")
.font(Fonts.button)
}).buttonStyle(StelloHollowButtonStyle())
}
}
}.accentColor(.black)
}
}
.padding()
.environmentObject(baseNavVM)
.ignoresSafeArea()
}
}

SwiftUI NavigationView nested in PageTabView wrong aligned on first appear

The NavigationViews inside my PageTabView are wrong aligned on first appear.
When i scroll to another page on my PageTabView and go back to the first page, the alignment is correct.
The content of the navigationview (red) is beneath the navigationbar on first appear.
Image of first appearance of the NavigationView
Image of the second appearance of the NavigationView
struct ContentView: View {
var body: some View {
TabView {
ForEach(0..<3) { index in
NavigationView {
Color.red
.navigationTitle("\(index). Page")
}
.navigationViewStyle(StackNavigationViewStyle())
}
}
.tabViewStyle(.page)
}
}
Edit:
I want to build the layout of the rooms tab in the apple home app in compact mode. Therefore the TabView in the code above gets wrapped in another tabview without the pagetabviewstyle modifier.
This works, but the same extracted problem in the code above happens.
var body: some View {
NavigationView {
TabView {
ForEach(0..<3) { index in
Color.red
.navigationTitle("\(index). Page")
}
}
.tabViewStyle(.page)
}
}
Just moved NavigationView outside, it fixed the problem

Creating a navbar with 3 items

I'm trying to create something like this:
A navigation bar with 3 items, is it possible to do this using navigationBarItems?
My current plan is to hide the navbar using:
.navigationBarTitle("")
.navigationBarHidden(true)
and then creating the 3 buttons using a HStack. The Problem I have is because I'm hiding the navbar, the click of one of the buttons take it to another view, which also then hides the navbar (Thats not what im looking for)
I have tried:
.navigationBarItems(trailing:
HStack {
Button("About") {
print("About tapped!")
}
Button("Help") {
print("Help tapped!")
}
}
)
But this creates the two items next to each other on the right side. I tried putting a Spacer() in the above HStack, but this doesn't work.
I would prefer to use navigationBarItems but can't seem to find a way to centre an item?
A navigation bar with 3 items, is it possible to do this using navigationBarItems?
No. Moreover navigationBarItems modifier is deprecated since SwiftUI 2.0
SwiftUI 2.0
This can be done with toolbar modifier as easy as attach it to any view inside NavigationView
Demo prepared & tested with Xcode 12 / iOS 14:
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: {}) { Image(systemName: "gear") }
}
ToolbarItem(placement: .principal) {
Button(action: {}) { Image(systemName: "car") }
}
ToolbarItem(placement: .navigation) {
Button(action: {}) { Image(systemName: "chevron.left") }
}