var body: some View {
NavigationView{
ZStack(alignment: .leading){
ZStack(alignment: .top){
VStack{
HStack(alignment: .top) {
Image(systemName: "chevron.left")
.font(.title2)
Text("profile")
.fontWeight(.bold)
Spacer()
Button(action: {
}) {
Image(systemName: "person.crop.circle.fill.badge.plus")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 24)
Text("subscribe")
Button(action: {
}) {
Image("share_black_24dp")
.tint(Color.white)
.foregroundColor(Color.white)
}
}
.foregroundColor(Color.white)
}
.frame(width: UIScreen.main.bounds.width - 20, height: 40)
.padding(.horizontal, 20)
.background(Color.teal)
}
// .navigationBarItems(leading: backButton)
ScrollView(.vertical, showsIndicators: false){
}
}
}
.navigationBarTitle("")
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
}
}
where does
.navigationBarTitle("")
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
need to be!?
I also tried it for NavigationView and it doesn't work
Your issue is that you have multiple NavigationViews.
NavigationView creates a new stack of views. Only your main view should have a NavigationView. The child views can use NavigationLink to push new views, but they should not create another NavigationView.
Think of it like this. NavigationView creates that stack to hold the views, and NavigationLink pushes a new view onto the stack. You only want to create one stack.
So, get rid of NavigationView in your View above, because it is linked from the main view which creates the NavigationView. Then, your code to hide the navigation bar will work as you expect.
Related
I'm looking how to align text to the top of screen, do you know how to?
import SwiftUI
struct RegisterSignInScreen: View {
var body: some View {
VStack {
Text("Welcome Back!")
.font(.title)
.fontWeight(.bold)
.multilineTextAlignment(.center)
.padding(.bottom, 5.0)
Text("Please sign in to your account")
.font(.subheadline)
.fontWeight(.bold)
.foregroundColor(Color.gray)
.multilineTextAlignment(.center)
}
}
}
struct RegisterSignInScreen_Previews: PreviewProvider {
static var previews: some View {
RegisterSignInScreen()
}
}
image
I tried to embed my VStack in a ZStack:
ZStack(alignment: .top)
But it didn't work.
To see why this is happening you can add a background to your VStack or ZStack
ZStack {
VStack {
//Text items
}
}
.background(.red)
What you will notice (maybe unexpectedly) is that the stack is only as big as it needs to be to contain the text items.
When you add alignment to the stack it aligns the content within the stack to the specified edge of the relatively small stack. It doesn't align the stack to an edge of the screen, or change the size of the stack. What you're actually looking to do is align the stack, not it's content.
In order to align to the top of the screen you can make the stack fill the entire height of the screen. Either by adding a Spacer() at the bottom of the VStack that will fill the remaining vertical space pushing the content upwards, or by applying a frame with .infinity maxHeight: and top aligned content to the VStack.
VStack {
Text("Hello World!")
Spacer()
}
VStack {
Text("Hello World!")
}
.frame(maxHeight: .infinity, alignment: .top)
Alternatively if required for your view, you can do a similar thing with a second stack containing your text stack like so:
var body: some View {
VStack {
welcomeText
Spacer()
}
}
var welcomeText: some View {
VStack {
Text("Welcome Back!")
.font(.title)
.fontWeight(.bold)
.multilineTextAlignment(.center)
.padding(.bottom, 5.0)
Text("Please sign in to your account")
.font(.subheadline)
.fontWeight(.bold)
.foregroundColor(Color.gray)
.multilineTextAlignment(.center)
}
}
You can do this in a couple of ways, but the most obvious way is to simply add a Spacer() in the bottom of the VStack
Like so:
struct RegisterSignInScreen: View {
var body: some View {
VStack {
Text("Welcome Back!")
Text("Please sign in to your account")
Spacer() // <- HERE
}
}
}
This will push your content in the VStack to the top.
Alternatively, you can add a frame modifier and force your VStack height and add the alignment there using .frame
struct RegisterSignInScreen: View {
var body: some View {
VStack {
Text("Welcome Back!")
Text("Please sign in to your account")
}
.frame(maxHeight: .infinity, alignment: .top) // <- HERE
}
}
ZStack(alignment: .top) works, but not the same way as you think)
try to do:
ZStack(alignment: .top){
}
.background(Color.green)
and you will understand why so :)
you need to use spacer :)
VStack {
YourView()
Spacer()
}
is anybody able to see why I am unable to navigate to a new view I have created called "FavouritesView" using NavigationLink?
this is the code of the HomeView where I am navigating from
var body: some View {
VStack(spacing: 0) {
Text("test")
.font(.title.bold())
.frame(maxWidth: .infinity)
.overlay(alignment: .trailing) {
NavigationLink {
FavouritesView()
} label: {
Image(systemName: "doc.badge.gearshape")
.font(.title3)
.foregroundColor(.white)
.padding(.trailing, 20)
}
}
.padding(.bottom, 10)
all I'm doing is putting in a navigation link at the top right next to the title
. just want to tap and goto my other view. Probably something im missing here anyone know the fix ?
thanks
Wrap your VStack in a NavigationView like so:
var body: some View {
NavigationView {
VStack(spacing: 0) {
Text("test")
.font(.title.bold())
.frame(maxWidth: .infinity)
.overlay(alignment: .trailing) {
NavigationLink {
FavouritesView()
} label: {
Image(systemName: "doc.badge.gearshape")
.font(.title3)
.foregroundColor(.white)
.padding(.trailing, 20)
}
}
.padding(.bottom, 10)
And if you're using Xcode 14 beta, use the new NavigationStack for a more Advanced implementation. See this.
I am trying to create below design using swiftUI but not able to find proper approach.
I tried but my image is not covering back button but coming below to back button
Expected design
VStack(spacing: 16) {
VStack {
ZStack(alignment: .topTrailing) {
Image("defaultImage")
.resizable()
.frame( height: 200)
Button("Cancel", action: {
print("cancel")
})
.padding(12)
}
}
}
My Design :(
You might want to do a lot of try in SwiftUI to get a custom design right. gave it a quick try for you and added comments on the code so you can understand most of what i did.
this is the quick result i got (with a random background i got on internet)
import SwiftUI
struct FirstView: View{
var body: some View{
NavigationView {
VStack{
NavigationLink(destination: BackgroundImageNav()){
Text("Go to the view")
.font(.title)
}
}
}
}
}
struct BackgroundImageNav: View {
#Environment(\.presentationMode) var presentationMode
// remplacing the back button action, (only problem is that this disable the swipe back)
var body: some View {
ZStack {
// ZStack help you having your image behind the other views
VStack {
Image("defaultImage")
.resizable()
.frame(height: 180)
.edgesIgnoringSafeArea(.all)
Spacer()
// having a spacer that push the image on the top and ignoring the safe area
}
VStack(alignment:.leading){
HStack{
Button(action:{
presentationMode.wrappedValue.dismiss()
// back button action
}){
Image(systemName:"chevron.left")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 30, height: 30)
.foregroundColor(.white)
}
Spacer()
Rectangle()
.fill(Color.white)
.frame(width: 200, height: 80, alignment: .center)
Spacer()
Button(action:{
// do something
}){
Image(systemName: "xmark")
.resizable()
.frame(width: 24, height: 24)
.foregroundColor(.white)
}
}.padding()
Text("Title")
.bold()
.font(.title)
.foregroundColor(.black)
.background(Color.white)
.padding(24)
Spacer()
}
}.navigationBarHidden(true)
// removing the bar to customize the back button
}
}
struct backgroundImage_Previews: PreviewProvider {
static var previews: some View {
FirstView()
}
}
In SwiftUI, when a NavigationLink is placed inside of a Form, an arrow automatically appears on the trailing side of the NavigationLink. How can the color of this arrow be changed?
struct example: View {
var body: some View {
NavigationView {
Form {
NavigationLink(destination: Text("Example destination")) {
Text("Example link")
}
}
}
}
}
Form/List is reusing UITableView and it's always been a problem to change the disclosure indicator tintColor *See: Question
So it comes to no surprise that .accentColor won't work here either.
The suggestions have mostly been to replace it with a custom view.
So lets do the same in SwiftUI.
Solution:
struct ContentView: View {
var body: some View {
NavigationView {
Form {
//Overlap NavigationLink and our Custom Cell arrangement
ZStack {
//Create a NavigationLink without the disclosure indicator
NavigationLink(destination: Text("Hello, World!")) {
EmptyView()
}
//Replicate the default cell
HStack {
Text("Custom UI")
Spacer()
Image(systemName: "chevron.right")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 7)
.foregroundColor(.red) //Apply color for arrow only
}
.foregroundColor(.purple) //Optional: Apply color on all inner elements
}
//Default style
NavigationLink(destination: Text("Hello, World!")) {
Text("Default UI")
}
}
}
}
}
NavigationLink with EmptyView gets rid of the default disclosure indicator
HStack is our Custom Cell View that replicates the default cell arrangement
Image(systemName: "chevron.right") is our replacement for the diclosure indicator
.foregroundColor will allow us to splash a color on either the entire HStack or just the Image (your choice)
ZStack allows to overlap the above two.
The NavigationLink basically makes the entire cell tappable
Result:
You can provide a custom view and hide the default NavigationLink arrow:
NavigationLink(destination: Text("Hello, World!")) {}
.opacity(0)
.background(
HStack {
Text("Custom UI")
Spacer()
Image(systemName: "chevron.right")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 7)
.foregroundColor(.red) //Apply color for arrow only
}
.foregroundColor(.purple)
)
Or specify the NavigationLink as background (so you have auto sizing):
HStack {
Text("Custom UI")
Spacer()
Image(systemName: "chevron.right")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 7)
.foregroundColor(.red) //Apply color for arrow only
}
.foregroundColor(.purple)
.background(
NavigationLink(destination: Text("Hello, World!")) {}
.opacity(0)
)
I'm trying to create a view in SwiftUI. In the preview, it looks like it should, but when run on my iPhone (or on the live preview) it looks like it is offset.
I tried to set the padding to -150, but then the TextField doesn't respond to touches.
VStack {
Text("Name:")
.padding(.bottom, 1)
TextField($name)
.padding(.horizontal, 25.0)
.textFieldStyle(.roundedBorder)
.frame(maxWidth: 500)
Text("Image:")
.padding(.top, 1)
Image(uiImage: image!)
.resizable(capInsets: EdgeInsets(), resizingMode: .stretch)
.scaledToFit()
.frame(width: 250, height: 250)
.clipShape(RoundedRectangle(cornerRadius: 10))
.padding(.top, 5)
Button(action: {
withAnimation {
self.showImagePicker = true
}
}) {
Text("Select Image")
.color(.init(red: 20/255, green: 146/255, blue: 81/255))
}
Button(action: {
let list = LSList( title: self.name,
image: self.image!,
id: 0)
list.add()
self.userData.listsData.append(list)
}) {
Text("Add List")
.color(.white)
.font(.system(size: 25))
.bold()
.padding(.horizontal, 7)
.frame(height: 35)
.background(Color.green)
.clipShape(RoundedRectangle(cornerRadius: 3))
}
Spacer()
} .navigationBarTitle(Text("Add List"))
The view in the preview:
The view on my iPhone:
I had the same issue, but found the the problem I had was in using navigationView multiple times.
I thought that we should have NavigationView in every view, but apparently, we should place navigationView only in the main view of the application, and all other views that we enter via navigationLink, automatically get the back option without the need to mention NavigationView again.
So check if you use navigationView more than once in your code.
Strangely, we can specify navigationBarTitle even in views that dont have the navigationView mentioned in them, this is because the navigationView is at the parent view.
Use "displayMode: .inline", to make the navigation area as minimal as possible, it will save you real-estate.
Another thing to do, is to use Spacer().
If you want all your items to be at the top, just put Spacer() as the last item in VStack, and it will push all items to the top.
See this example:
VStack {
// What you care about displaying
Text("Something to Show 1")
Text("Something to Show 2")
Text("Something to Show 3")
// This should be the last, put everything to the top
Spacer()
}
.navigationBarTitle(Text("The Title"), displayMode: .inline)
I had a similar issue, I wanted a VStack to align its content on the top of the screen, and was only using a NavigationView in the parent, but the VStack showed centered. What fixed it for me was using a Spacer(), like this:
VStack(alignment: .leading, spacing: 10){
HStack(alignment: .center, spacing: 5.0) {
...
}
Group{
...
}
Spacer() //<-- This solved my problem
}
Assuming that your VStack is wrapped in a NavigationView, this is the reason it is not rendering correctly in the simulator. The reason it shows fine in preview is that it is not displaying the navigation bar (which includes the back button as well) because the canvas doesn’t know this view might be pushed but in runtime the navigation bar is added while you’re also using an extra NavigationView as well.
To fix it unwrap the VStack from NavigationView and simply remove this NavigationView from the child view.
To make it visible correct with Navigation items in previews(even for child views) you need to wrap the View into the NavigationView { }, because the Canvas is an empty clean environment and it doesn't know that the View may be pushed into the NavigationView
To fix it on iPhone makes sure you are correctly pushing the child view. It should be NavigationButton(destination: AddList()) {}
Example of RowView implementation:
NavigationButton(destination: CarDetail(car: car)) {
HStack {
VStack(alignment: .leading) {
Text(car.name)
Text(car.isAvailable ? "Is Available" : "Out of stock")
.font(.subheadline)
.foregroundColor(.secondary)
}
}
}
ScrollView(.vertical){
VStack {
Text("Name:")
.padding(.bottom, 1)
TextField($name)
.padding(.horizontal, 25.0)
.textFieldStyle(.roundedBorder)
.frame(maxWidth: 500)
Text("Image:")
.padding(.top, 1)
Image(uiImage: image!)
.resizable(capInsets: EdgeInsets(), resizingMode: .stretch)
.scaledToFit()
.frame(width: 250, height: 250)
.clipShape(RoundedRectangle(cornerRadius: 10))
.padding(.top, 5)
Button(action: {
withAnimation {
self.showImagePicker = true
}
}) {
Text("Select Image")
.color(.init(red: 20/255, green: 146/255, blue: 81/255))
}
Button(action: {
let list = LSList( title: self.name,
image: self.image!,
id: 0)
list.add()
self.userData.listsData.append(list)
}) {
Text("Add List")
.color(.white)
.font(.system(size: 25))
.bold()
.padding(.horizontal, 7)
.frame(height: 35)
.background(Color.green)
.clipShape(RoundedRectangle(cornerRadius: 3))
}
Spacer()
} .navigationBarTitle(Text("Add List"))
}