SwiftUI: Navigation link alignment with the newer navigation stack - swift

I am using the new NavigationStack and I have a VStack with the code below:
VStack(alignment: .leading) {
NavigationLink(post.phrase, value: post)
.lineLimit(2)
.font(.system(size: 20))
.multilineTextAlignment(.leading)
.foregroundColor(.black)
Text(post.Translation.chinese)
.lineLimit(1)
}
The NavigationLink is always centrally aligned but the Text is ok which is left aligned. Is there a way to force the 2-line NavigationLink to align to the left?

The code below will correctly align the navigation link:
VStack(alignment: .leading) {
NavigationLink(value: post) {
Text(post.phrase)
.lineLimit(2)
.font(.system(size: 20))
.multilineTextAlignment(.leading)
.foregroundColor(.black)
}
Text(post.Translation.chinese)
.lineLimit(1)
}

Related

How to align text to the left and in the middle of a view

I have two Texts: Text("1") and Text("2") in an HStack. I want Text("1") to be in the leftmost part of ContentView and Text("2") to be in the exact horizontal center of ContentView.
Here's my code:
import SwiftUI
struct ContentView: View {
var body: some View {
HStack {
Text("1")
.multilineTextAlignment(.leading)
.frame(
alignment: .leading
)
Text("2")
.multilineTextAlignment(.center)
.frame(
alignment: .center
)
}
.frame(width: .infinity)
}
}
When I run this though, both Text("1") and Text("2") remain in the general horizontal center of ContentView. Not sure what I'm doing wrong.
Here's another way you can do this by using ZStack. Second text will always be in exact centre.
ZStack {
HStack {
Text("1")
Spacer()
}
HStack {
Spacer()
Text("2")
Spacer()
}
}
.padding()
Try the below code:
HStack {
Text("1")
.multilineTextAlignment(.leading)
Text("2")
.multilineTextAlignment(.center)
.frame(minWidth: 0, maxWidth: .infinity)
}
Add a Spacer to your HStack after each Text. This will give you the first Text at the left and the second starting in the middle
HStack {
Text("1")
.multilineTextAlignment(.leading)
.frame(alignment: .leading)
.padding(.leading)
Spacer()
Text("2")
.multilineTextAlignment(.center)
.frame(alignment: .center)
.padding(.trailing)
Spacer()
}

Why do the elements inside my VStack inside a HStack still go vertical

So basically this is my code.
Text("Melbourne, Victoria")
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(Color.white)
.padding(.bottom, 30)
Image(systemName: "moon.fill")
.foregroundColor(Color.white)
.font(.system(size: 60))
Text("Today")
.font(.title)
.fontWeight(.medium)
.foregroundColor(Color.white)
Text("34°C")
.font(.title3)
.fontWeight(.medium)
.foregroundColor(Color.white)
Spacer()
HStack {
Image(systemName: "sun.max.fill")
.foregroundColor(Color.yellow)
.font(.system(size: 40))
.padding(.bottom, 550)
Text("Mon 34°C")
.font(.title)
.fontWeight(.medium)
.foregroundColor(Color.white)
.padding(.bottom, 550)
}
}
.background(
Image("night")
.ignoresSafeArea()
)
I want to make more of the days in this weather app each with it's on SF Symbol and everything is inside this VStack. And the days and SF symbols are inside a HStack to keep them horizontal. But if I want to put more of those the next time I do it they go next to each other but the symbol goes on top look at this.
This is the image with only 1 of those days
And this one is when I put more than 1 but its next to each other when I want them vertically aligned.
This is the one if I put them in another VStack which makes the SF symbol go above the text
IS there any solution to this?
The problem is your .padding(.bottom, 550).
Image(systemName: "sun.max.fill")
.foregroundColor(Color.yellow)
.font(.system(size: 40))
.padding(.bottom, 550) /// here!
It's currently attached to your first Image. As a result, the HStack is stretched vertically and it appears as though the first Image is higher up than second one.
To fix, move both .padding(.bottom, 550)s to outside your HStack.
You have quite a lot of arbitrary values for padding. You should have your layout adapt to various devices, rather than hard-coding that .bottom spacing for example.
Working example:
struct ContentView: View {
var body: some View {
VStack(spacing: 40) {
Text("Melbourne, Victoria")
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(Color.white)
VStack {
Image(systemName: "moon.fill")
.foregroundColor(Color.white)
.font(.system(size: 60))
Text("Today")
.font(.title)
.fontWeight(.medium)
.foregroundColor(Color.white)
Text("34°C")
.font(.title3)
.fontWeight(.medium)
.foregroundColor(Color.white)
}
VStack(spacing: 10) {
HStack {
Image(systemName: "sun.max.fill")
.renderingMode(.original)
.font(.system(size: 40))
Text("Mon 34°C")
.font(.title)
.fontWeight(.medium)
.foregroundColor(Color.white)
}
HStack {
Image(systemName: "cloud.sun.fill")
.renderingMode(.original)
.font(.system(size: 40))
Text("Tue 28°C")
.font(.title)
.fontWeight(.medium)
.foregroundColor(Color.white)
}
}
Spacer()
}
.frame(maxWidth: .infinity)
.background(
Color(red: 0.34, green: 0.36, blue: 0.71)//Image("night")
.ignoresSafeArea()
)
}
}
Result:
Although there is already an outer VStack, they are nested VStacks because they have different amounts of padding. Multiple views are grouped together, and then those are grouped together with larger paddings to separate them.
Bonus
SF Symbols colors
Use:
.renderingMode(.original)
Rather than:
.foregroundColor(Color.yellow)
To color the SF Symbols with the default colors, as shown in the above example.
Align days
You can align the days across each HStack with a custom alignment guide. Use the following:
extension HorizontalAlignment {
struct LeadingDay: AlignmentID {
static func defaultValue(in context: ViewDimensions) -> CGFloat {
context[.leading]
}
}
static let leadingDay = HorizontalAlignment(LeadingDay.self)
}
Making the other following changes:
VStack(alignment: .leadingDay, spacing: 10) { // <- HERE
HStack {
Image(systemName: "sun.max.fill")
.renderingMode(.original)
.font(.system(size: 40))
Text("Mon 34°C")
.font(.title)
.fontWeight(.medium)
.foregroundColor(Color.white)
.alignmentGuide(.leadingDay) { d in // <- HERE
d[.leading]
}
}
HStack {
Image(systemName: "cloud.sun.fill")
.renderingMode(.original)
.font(.system(size: 40))
Text("Tue 28°C")
.font(.title)
.fontWeight(.medium)
.foregroundColor(Color.white)
.alignmentGuide(.leadingDay) { d in // <- HERE
d[.leading]
}
}
}
Result:

SwiftUI : How to ignore NavigationView When Add ScrollView

My previous code is
VStack {
MapView(coordinate: landmark.locationCoordinate)
.frame(height: 300, alignment: .center)
.edgesIgnoringSafeArea(.top)
CircleImageView(image: landmark.image)
VStack(alignment: .leading) {
Text("\(landmark.name)")
.font(.title)
.multilineTextAlignment(.center)
HStack {
Text("\(landmark.park)")
Spacer()
Text("\(landmark.state)")
}
.font(.subheadline)
.foregroundColor(.secondary)
Divider()
Text("\(landmark.category)")
.font(.title2)
Text("\(landmark.description)")
}
.padding()
Spacer()
}
My current build works fine. But when I add ScrollView as parent of my code, the map does not ignore the safe area.
Current build
After adding ScrollView
I used edgesIgnoringSafeArea(.all) but it didn't work. By the way, I am new to SwiftUI so I will appreciate any help.

My TextField in Swift UI is Unresponsive to taps and clicks, text cannot be input, is there an issue with the code?

Hi I'm an intermediate level engineer with swift and swift UI.
Currently, I am having problems with the TextField(), it is unresponsive to taps and clicks, and hence the keyboard does not show up,
However, it does show up when it is one of two main elements within a VStack, but anymore than that and it does not work,
Is there an issue with the code? and can anyone find a fix or a work around for this?
Thanks, Miles
{
#State var textField = ""
var body: some View {
returnJoinModalContent()
}
func returnJoinModalContent() -> some View{
let accentColor = Color.blue
return VStack(alignment: .center){
HStack{
Text("Join Game")
.bold()
.font(.largeTitle)
.padding()
Spacer()
Button(action:{
//self.hideModal()
}){
Image(systemName: "xmark.circle.fill")
.resizable()
.frame(width: 50,height: 50)
.foregroundColor(accentColor)
.padding()
}
}
.padding(.bottom,170)
VStack(alignment: .leading){
TextField("Enter Game Code",text: self.$textField)
.font(.largeTitle)
Rectangle()
.frame(height: 6)
.foregroundColor(accentColor)
}
.padding()
HStack{
Button(action:{
//self.joinGame()
}){
ZStack{
RoundedRectangle(cornerRadius: 90)
.frame(width: 200,height: 70)
.foregroundColor(accentColor)
Text("Ready!")
.bold()
.font(.title)
.foregroundColor(Color.white)
}
}
}
.padding(.vertical,20)
HStack{
Image(systemName: "info.circle")
.resizable()
.frame(width:60,height:60)
.foregroundColor(accentColor)
Text("Ask your host for the game code, it can be found at the bottom of the player lobby")
.padding()
Spacer()
}
.padding(.top,60)
.padding(.horizontal,20)
Spacer()
}
.padding()
}
}
This seems to be one of those things in swiftUI that is difficult to track down. I found the problem is your ready button. More specifically the label being a ZStack with a colored rounded rectangle as the background. If you replace your button's label with the following your text field should be selectable.
Text("Ready!")
.bold()
.font(.title)
.foregroundColor(Color.white)
.frame(width: 200,height: 70)
.background(accentColor)
.mask(RoundedRectangle(cornerRadius: 90))
I've found that overlay on the TextField or the container of TextField might cause it to be unresponsive
you should remove it and replace it with ZStack

VStack inside ForEach loop not respecting alignment parameter in WatchOS

I have a VStack with alignment .leading inside of a ForEach loop inside a ScrollView and the alignment parameter is not being respected. If I have a single VStack outside of the ForEach loop the alignment parameter is being used and the view is displayed correctly.
ScrollView{
// THIS DISPLAYS CORRECTLY
VStack(alignment: .leading){
Text("namename")
.font(.headline)
.lineLimit(1)
Text("namename name")
.font(.subheadline)
.lineLimit(1)
}
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.gray.opacity(0.20))
.cornerRadius(5)
.padding(.bottom)
ForEach(self.list_of_names, id: \.self) { item in
// THIS DOES NOT DISPLAY CORRECTLY
VStack(alignment: .leading){
Text(item)
.font(.headline)
.lineLimit(1)
Text(item + " name")
.font(.subheadline)
.lineLimit(1)
}
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.gray.opacity(0.20))
.cornerRadius(5)
.padding(.bottom)
}
}
.padding()
The first row has the correct alignment and it's outside the ForEach loop, meanwhile the other rows are inside the loop. The blue lines represent me highlighting each VStack inside the ForEach loop
The VStacks created in the ForEach loop do seem to be conforming to the alignment parameter. Aligning the text to the leading edge only applies to the shorter items in the VStack.
In the top VStack, "namename" at the top is only that far to the left because "namename name" below is that much wider from the center of the ScrollView. So the top VStack is not the proper way to fully achieve the alignment that you want to the ScrollView.
What you're looking for:
Leave the alignment parameter for VStack.
Add the alignment parameter to the frame of the VStack.
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
I'm a bit late, but another solution I usually use is wrapping the values in an HStack and adding a Spacer. Something like this will achieve the desired effect:
var body: some View {
ScrollView {
ForEach(self.list_of_names, id: \.self) { item in
HStack {
VStack(alignment: .leading) {
Text(item)
.font(.headline)
.lineLimit(1)
Text(item + " name")
.font(.subheadline)
.lineLimit(1)
}
Spacer()
}
.padding()
.frame(minWidth: 0, maxWidth: .infinity)
.background(Color.gray.opacity(0.20))
.cornerRadius(5)
.padding(.bottom)
}
}
.padding()
}