Adding shapes in List row of SwiftUI

Viewed 907

I am trying to create a List View where rows looks like this:

enter image description here

However, I am unable to align the Circle on the leading side. Tried using Spacer(), HStack within VStack, it just doesn't work. Here's my code and its output.

struct PeopleView: View {
    
    let people = ["Adam", "James"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(people, id: \.self) { person in
                    HStack {
                        Circle()
                        VStack {
                            Text("\(person)")
                        }
                    }
                }
            }
            .navigationBarTitle("People", displayMode: .inline)
        }
    }
}

tui

3 Answers

Actually you don't need shape itself in this case, but only as a mask to visually present text in circle.

So the solution can be like following

demo

HStack {
    Text(person.prefix(2).uppercased()).bold()
        .foregroundColor(.white)
        .padding()
        .background(Color.red)
        .mask(Circle())          // << shaping text !!

    Spacer()
    VStack {
        Text("\(person)")
    }
}

Some views in SwiftUI fill all available space. Such views are shapes, colors, spacers, dividers, and GeometryReader.

Your Circle is a shape and it behaves similarly like a Spacer (in terms of filling space).

If you replace Circle with an image of a circle it will work:

ForEach(people, id: \.self) { person in
    HStack {
        Image(systemName: "circle.fill")
            .imageScale(.large)
        Spacer()
        VStack {
            Text("\(person)")
        }
    }
}

That is happening because you did not give a fixed (or relative) frame to the Circle Shape, so the Circle is taking up the maximum available width.

If you add a frame(width:height:), everything should work correctly:

The expected result

struct PeopleView: View {
    
    let people = ["Adam", "James"]
    
    var body: some View {
        NavigationView {
            List {
                ForEach(people, id: \.self) { person in
                    HStack {
                        Circle()
                            .frame(width: 50, height: 50)
                        VStack {
                            Text("\(person)")
                        }
                    }
                }
            }
            .navigationBarTitle("People", displayMode: .inline)
        }
    }
}
Related