SwiftUI rectangle taking up the wrong amount of space - swift

I made a comment feed for a subreddit I moderate and I wanted to make a vertical line on the left side of the comment underneath the title of the post in SwiftUI. I made the line using a rounded rectangle but the problem is instead of shaping itself to the height of the text, it is a certain height and makes the text conform to that height. Any idea how to fix this? Thanks!
Screenshot
Code
VStack {
HStack {
Text(comment.link_title ?? "")
.font(.callout)
.bold()
.padding(.horizontal, 5)
.foregroundColor(Color("black"))
Spacer()
}
HStack {
RoundedRectangle(cornerRadius: 2, style: .continuous)
.frame(width: 3)
.foregroundColor(Color("medGray"))
.padding(.leading, 10)
Text(comment.body ?? "")
.font(.body)
.padding(5)
.foregroundColor(Color("black"))
Spacer()
}
}

You can achieve this by simply using an overlay.
Checkout the following example:
HStack {
Text("Lorem ipsum")
.font(.body)
.padding(.leading, 20)
.foregroundColor(Color.black)
Spacer()
}.overlay(RoundedRectangle(cornerRadius: 2, style: .continuous)
.frame(width: 3)
.foregroundColor(Color.gray)
.padding(.leading, 10),
alignment: .leading)

Related

Expand HStack within List to go end to end but not top to bottom so it looks like there are wider spaces between items

I've been trying to create a list and expand the space between the rows, while keeping them the full width, but I seem to be having some challenges. I think the approach is to make the HStack within the list expand horizontally from end to end and try to narrow top and bottom. I thought a frame modifier would do this but it doesn't seem to be working.
Here is the code:
NavigationView() {
List(caseList) {caseItem in
HStack {
Image(systemName: "folder.fill.badge.person.crop")
.foregroundColor(.accentColor)
VStack(alignment: .leading, spacing: 5) {
Text(caseItem.alias)
Text("# team members")
.font(.subheadline)
.foregroundColor(.secondary)
}
}
.listRowInsets(EdgeInsets())
.background(Color.green)
.clipShape(RoundedRectangle(cornerRadius: 10))
.badge(Int.random(in: 0..<5))
.listRowSeparatorTint(Color.cyan, edges: .all)
.listRowSeparator(.visible)
.listRowBackground(Color.orange)
.frame(
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .topLeading
)
}
.listStyle(InsetGroupedListStyle())
}
.onAppear() {
loadCases()
}
.navigationTitle("Cases")
I would also like to delete the gap between the list items and cases at the top.
UPDATE
I added a 2nd image to show, in red, what I would like the green shape to cover. I guess my goal is to make them look a little more like independent items with additional information and bigger spaces between them. This should not be an exhaustive list and in most occasions people will only have one, so I am trying to make them of substance. I was toying with expanded/collapsed ones so if you only had one, it would be expanded and not look so lonely.
If I understood the goal correctly, here it is (tested with Xcode 13.4 / iOS 15.5)
HStack {
Image(systemName: "folder.fill.badge.person.crop")
.foregroundColor(.accentColor)
VStack(alignment: .leading, spacing: 5) {
Text(caseItem.alias)
Text("# team members")
.font(.subheadline)
.foregroundColor(.secondary)
}
Spacer()
}
.badge(Int.random(in: 0..<5)).padding(.horizontal)
.listRowInsets(EdgeInsets(top: 8, leading: 0, bottom: 8, trailing: 0))
.background(Color.green)
.listRowSeparatorTint(Color.cyan, edges: .all)
.listRowSeparator(.visible)
.listRowBackground(Color.orange)
If i understood correctly, you want to space out your Items inside of your list?
in this case, you can add some padding(EdgeInsets(top: 15, bottom: 15))
"change the cursive text to the values that you want"
this would look something like this:
NavigationView() {
List(caseList) {caseItem in
HStack {
Image(systemName: "folder.fill.badge.person.crop")
.foregroundColor(.accentColor)
VStack(alignment: .leading, spacing: 5) {
Text(caseItem.alias)
Text("# team members")
.font(.subheadline)
.foregroundColor(.secondary)
}
}
.listRowInsets(EdgeInsets())
.background(Color.green)
.clipShape(RoundedRectangle(cornerRadius: 10))
.badge(Int.random(in: 0..<5))
.listRowSeparatorTint(Color.cyan, edges: .all)
.listRowSeparator(.visible)
.listRowBackground(Color.orange)
.padding(EdgeInsets(top: 15, bottom: 15))
.frame(
maxWidth: .infinity,
minHeight: 0,
maxHeight: .infinity,
alignment: .topLeading
)
}
.listStyle(InsetGroupedListStyle())
}
.onAppear() {
loadCases()
}
.navigationTitle("Cases")
Hope that helped you! if you need anymore help, you can contact me over on GitHub or Discord! (Discord on my profile)

SwiftUI How to align the bottom of two text with different font size?

I’m trying to align the bottom of two Text but the larger one looks like thismy widget looks like this. I don’t know why there’s still some space below this Text view.
This is my code:
var body: some View {
GeometryReader{geometry in
ZStack(alignment: .center){
Image("background")
.resizable()
VStack(){
HStack(alignment: .bottom){
Text("3")
.lineLimit(1)
.font(.bold(.system(size: 100))())
.minimumScaleFactor(0.1)
.foregroundColor(Color.white)
.frame(width: nil, height: geometry.size.height/3, alignment: .bottom)
.lineLimit(1)
.shadow(radius: 2)
Text("cups")
.foregroundColor(Color.white)
.font(.system(size: 12))
.shadow(radius: 2)
}
Text("Next cup on")
.foregroundColor(Color.white)
.font(.system(size: 10))
.shadow(radius: 2)
.opacity(0.5)
Text("10 : 00")
.foregroundColor(Color.white)
.font(.system(size: 12))
.shadow(radius: 1)
.opacity(0.5)
}
}
}
}
What I want is the number 3’s bottom aligned to “cups”’s bottom.
Thanks!
Instead of .bottom, you can use .lastTextBaseline as your HStack alignment:
HStack(alignment: .lastTextBaseline) {
Text("Hello").font(.system(size: 40))
Text("World").font(.system(size: 10))
}

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:

Adding 2 backgrounds within a Z and HStack?

The color.red is my widgets main background but I would like to add a black background to the top behind the text "Line1" and image "2". So basically a black bar that stretches across the top under the text and image.
var body: some View {
ZStack {
Color.red
VStack(alignment: .leading, spacing: 0) {
HStack {
Text("Line1")
.foregroundColor(.orange)
.bold()
.font(.system(size: 17.5))
.padding(.top)
Spacer()
Image("2")
.resizable()
.frame(width: 25, height: 25)
.padding(.top)
}
.padding(.horizontal)
.border(Color.green)
VStack(alignment: .leading) {
Image("2")
.resizable()
.frame(width: 67, height: 30)
Text("State")
.foregroundColor(Color.green)
.font(.system(size: 15))
Text("1")
.foregroundColor(Color.blue)
.font(.system(size: 10))
.opacity(0.5)
Spacer()
Spacer()
}
.padding(.horizontal)
.border(Color.blue)
}
}
}
You can add a .background modifier to your first HStack:
HStack {
//content here
}
.padding(.horizontal)
.border(Color.green)
.background(Color.black)
Keep in mind that order of modifiers is important, so if you put the background before the padding, the padding will not have that background color -- that's why I used it last.

SwiftUI bug with ScrollView appearance to the scene

I have problem in SwiftUI. I created ScollView and post into some Views. (News Articles). When i launch app - ScrollView and content inside appears in dioganal way, like animation. But i need to launch app and get static ScrollView with views inside it, without any movements.
Also the same problem occurred when i open sheet view with ScrollView and Text Blocks inside. It also appers first 0.3s like dioganaly way. But how can i achive static ? Thank you all )
Place i use sheet controller (Also this block in ScrollView)
ScrollView{
ArticlePreView(image: "one", category: "Category", heading: "Header", author: "some text").onTapGesture {
self.showingDetail.toggle()
}.sheet(isPresented: $showingDetail) {
Home()
}
}
Image to understand
Video of problem
And this is place of my sheet controller
ScrollView() {
VStack {
HStack {
Text("Soem long title")
.font(.title)
.fontWeight(.bold)
Spacer()
Button(action: {
}) {
HStack {
Image(systemName: "heart.fill")
.foregroundColor(Color.gray)
}
.padding()
}
.background(
Circle()
.fill(Color.neuBackground)
)
.shadow(color: .dropShadow, radius: 15, x: 10, y: 10)
.shadow(color: .dropLight, radius: 15, x: -10, y: -10)
}
.padding(.horizontal, 35)
.padding(.top, 25)
Text("long text")
.multilineTextAlignment(.leading)
.foregroundColor(.gray)
.padding(.horizontal, 30)
.padding(.top, 20)
Text("long text")
.multilineTextAlignment(.leading)
.foregroundColor(.gray)
.padding(.horizontal, 30)
.padding(.top, 20)
Text("long text")
.multilineTextAlignment(.leading)
.foregroundColor(.gray)
.padding(.horizontal, 30)
.padding(.top, 20)
Text("long text")
.multilineTextAlignment(.leading)
.foregroundColor(.gray)
.padding(.horizontal, 30)
.padding(.top, 20)
Spacer(minLength: 50)
}
}.frame(width: UIScreen.main.bounds.size.width)
Fixed using
.frame(width: UIScreen.main.bounds.size.width)
.fixedSize()
SwiftUI is not adaptive