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

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)

Related

Align elements both leading and trailing in same container, without stretching it, in SwiftUI

I'm trying to build a simple chat with a design like the most usual messengers.
A message consists of a user name (if not your own message), the message itself and a timestamp.
I want the width of a message to be determined by the widest child element (most likely the message, but in rare cases maybe the user name or timestamp).
I also want the user name and message to be aligned leading/left and the timestamp to be aligned trailing/right, just like group chats in WhatsApp, Signal or the likes..
I tried weird amounts of H/V/Z-Stacks, which lead to weird happenings. I also tried both adding Spacers and maxLength = .infinity, which lead to the message stretching to the far right with lots of empty space.
My current code has all elements aligned centered:
And this is what I want:
This code is only for the comment, which itself is embedded into a ScrollView/VStack for each one.
HStack() {
if comment.author?.id == currentUserId {
Spacer()
.frame(width: 50)
Spacer()
}
VStack(spacing: 3) {
if comment.author?.id != currentUserId {
Text("Test User")
.font(.body)
.frame(alignment: .leading)
.border(.red)
}
Text("Test message content")
.frame(alignment: .leading)
.border(.red)
Text(date)
.foregroundColor(.gray)
.frame(alignment: .trailing)
.border(.red)
}
.border(.green)
.padding(10)
.background(Color.gray)
.cornerRadius(10)
if comment.author?.id != currentUserId {
Spacer()
Spacer()
.frame(width: 50)
}
}
Also I thought the double Spacers on the left or right side looked kinda weird. I tried using .frame(minWidth: 50), which ended up way too wide and pushes even a small message like the one on the image into a second line.
I'm happy for any ideas for these problems, but I'm trying to go for a simple solution and no complex calculations with alignmentGuides or GeometryReader or similar.
.frame allows you to specify the alignment.
So you could just make the VStack leading and then use .frame on the last element with alignment: .trailing. Keep in mind that the View will then grow to its available space. If you want to prevent that, just add .fixedSize() (or .fixedSize(horizontal: true, vertical: false)) to the parent view.
GroupBox {
VStack(alignment: .leading) {
Text("Test User")
Text("Test Message Content")
Text("9.5.2022, 19:31")
.font(.caption)
.foregroundColor(.secondary)
.frame(maxWidth: .infinity, alignment: .trailing)
}
.fixedSize()
}
or if you want to keep the VStack on the default alignment
GroupBox {
VStack {
Text("Test User")
.frame(maxWidth: .infinity, alignment: .leading)
Text("Test Message Content")
Text("9.5.2022, 19:31")
.font(.caption)
.foregroundColor(.secondary)
.frame(maxWidth: .infinity, alignment: .trailing)
}
.fixedSize()
}
but it also works using a HStack + Spacer
GroupBox {
VStack(alignment: .leading) {
Text("Test User")
Text("Test Message Content")
HStack {
Spacer()
Text("9.5.2022, 19:31")
.font(.caption)
.foregroundColor(.secondary)
}
}
.fixedSize()
}

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))
}

SwiftUI rectangle taking up the wrong amount of space

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)

SwiftUI multiple TextField causing lags

I am using many TextFields in my SwiftUI Mac OS app. I am a main form, where the user adds data, which is composed of multiple Stacks/ views which contain TextFields/ and Text()
I noticed a strange bug, when I am using many TextFields combined in different views, I get some very heavy lags when selecting the TextField. Also when I skip to the next one with Tab it takes time.
It is really strange behavior and I am not sure what is causing that. I have a different view with many TextFields aswell, where everything is working smooth.
Also sometimes I can not jump back to the prior TextField with Shift+Tab.
Edit: I could figure out how to get rid of it. However, only if I remove one view. I don't want to.
My main container looks like that:
HStack
{
//Left Side
VStack{
Text("Here is the next #1")
}
VStack
{
//The View posted below
ViewBelow()
}
}
If I remove the first VStack, the issue is solved. Nothing lagging. If I add it, it is there again.
Just to give you a neckline of my code (many Stacks with TextFields)
ZStack
{
VStack
{
HStack
{
Text("Personal Data")
.font(.title)
.fontWeight(.bold)
.padding(.horizontal, 0)
.padding(.vertical, 5)
Spacer()
}
Divider()
.padding(.bottom, 5)
//Personal Data Types
HStack(spacing: 0)
{
//Left Element
VStack(alignment: .center)
{
Text("Vorname")
.foregroundColor(Color.gray)
} .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
//Right Elemenet
VStack()
{
Text("Nachname")
.foregroundColor(Color.gray)
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}.frame(minWidth: 0, maxWidth: .infinity)
HStack(spacing: 0)
{
VStack(alignment: .center)
{
//Left Element
if (self.editMode)
{
TextField("Enter some text", text: $s_test)
.frame(maxWidth:250)
}
else
{
Text(self.person.firstName)
.font(.body)
}
} .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
VStack()
{
//Left Element
if (self.editMode)
{
TextField("Enter some text", text: self.$s_test)
.frame(maxWidth:250)
}
else
{
Text(self.person.lastName)
.font(.body)
}
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}.frame(minWidth: 0, maxWidth: .infinity)
.padding(.top, 0)
//Personal Data Types
HStack(spacing: 0)
{
//Left Element
VStack(alignment: .center)
{
Text("Nickname")
.foregroundColor(Color.gray)
} .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
//Right Elemenet
VStack()
{
Text("Birthday")
.foregroundColor(Color.gray)
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}.frame(minWidth: 0, maxWidth: .infinity)
.padding(.top, 10)
HStack(spacing: 0)
{
VStack(alignment: .center)
{
//Left Element
if (self.editMode)
{
TextField("Enter some text", text: self.$s_test)
.frame(maxWidth:250)
}
else
{
Text(self.person.nickname)
.font(.body)
}
} .frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
VStack()
{
//Right Element
if (self.editMode)
{
TextField("Enter some text", text: self.$s_test)
.frame(maxWidth:250)
}
else
{
Text(self.person.birthdate)
.font(.body)
}
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .leading)
}.frame(minWidth: 0, maxWidth: .infinity)
.padding(.top, 0)
}
Maybe someone experienced the same already.. I am not quiet sure how to solve it. I removed many views, then it is working better. However I am not sure if it is just the quantity of TextFields or some bug in the other view.
I demonstrate the lag in the Gif. I press instantly when I hover above the TextField. See that lag..

how to create a fit HStack with equal space between it's object

I wanna create an HStack with levitating space between objects, but equal between each one and also it must fit on horizontal, Some of like that
I used Spacer() between objects, like that
HStack {
Text("Object1")
Spacer()
Text("Object2")
Spacer()
Text("ASASASA")
Spacer()
Text("asa")
}
.padding()
But there is just a question, Is there any way better than for making my code cleaner??
Maybe something like this? You might want to set the alignment: to what you need.
HStack(spacing: 20) {
Group {
Text("Object1")
Text("Object2")
Text("ASASASA")
Text("asa")
}
.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
}