Reputation: 1454
I would like to stack overlapping elements horizontally, like this:
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
Upvotes: 7
Views: 4644
Reputation: 154543
.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)
}
}
}
Upvotes: 2
Reputation: 8130
Here would be a more intuitive solution. You could instead use negative spacing and have only HStack
s:
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)
}
}
Upvotes: 11