Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI : stack overlapping elements horizontally?

Tags:

ios

swiftui

I would like to stack overlapping elements horizontally, like this:

enter image description here

Here is what I tried:

struct StackedElementsView: View {
    let colors: [Color] = [.red, .blue, .purple]
    
    var body: some View {
        HStack {
            ZStack {
                ForEach(0..<colors.count) { i in
                    ZStack(alignment: .leading) {
                        colors[i]
                            .clipShape(Circle())
                            .frame(width: 44, height: 44)
                    }
                    .offset(x: CGFloat(i) * 25)
                }
            }
            .padding(.leading, 24)
            Color.purple
                .frame(width: 100, height: 44)
            Spacer()
        }
        .padding(.vertical, 8)
    }
}

struct StackedElementsView_Previews: PreviewProvider {
    static var previews: some View {
        StackedElementsView()
    }
}

I have an issue with this, the purple rectangle overlaps the circles and I don't know why.

Thank you for your help

like image 369
Another Dude Avatar asked Jul 19 '26 19:07

Another Dude


2 Answers

Here would be a more intuitive solution. You could instead use negative spacing and have only HStacks:

enter image description here

struct StackedElementsView: View {
    let colors: [Color] = [.red, .blue, .purple]
    
    var body: some View {
        HStack {
            HStack(spacing: -25) {
                ForEach(0..<colors.count) { i in
                    colors[i]
                        .clipShape(Circle())
                        .frame(width: 44, height: 44)
                }
            }
            
            Color.purple
                .frame(width: 100, height: 44)
            Spacer()
        }
        .padding(.leading, 24)
        .padding(.vertical, 8)
    }
}
like image 178
Mofawaw Avatar answered Jul 21 '26 08:07

Mofawaw


.offset just changes where the view draws, but doesn't change the frame which is why the rectangle draws further left than you expect.

One way to fix this is to add appropriate leading padding to the rectangle:

Color.purple
    .frame(width: 100, height: 44)
    .padding(.leading, CGFloat(colors.count - 1) * 25)

Alternate solution

Instead of using .offset, use a Color.clear view in an HStack to provide the spacing needed:

ForEach(0..<colors.count) { i in
    ZStack(alignment: .leading) {
        HStack(spacing: 0) {
            Color.clear
                .frame(width: CGFloat(i) * 25, height: 44)
            colors[i]
                .clipShape(Circle())
                .frame(width: 44, height: 44)
        }
    }
}
like image 31
vacawama Avatar answered Jul 21 '26 09:07

vacawama



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!