Padding, offset, or position in SwiftUI

5.4k views Asked by At

I’m trying to position a circle to have its center sitting on top of a rectangle like this. The diameter of the circle doesn't have to be the same width as the rectangle.

enter image description here

What I’m trying to understand is what is the best and most practical way to accomplish this? Should I be using padding, offset, or position in this case and would it hold for different devices/screen sizes? It seems like any of them can be used but which one is more ideal?

Here’s what I have with using padding. I can increase the bottom padding to achieve what I want but not sure if that’s the best way.

Rectangle()
    .fill(Color.gray)
    .frame(width: 85, height: 175)
    .overlay(
        Circle()
            .fill(Color.black)
            .frame(width: 120)
            .padding(.bottom, 50)
    )

enter image description here

2

There are 2 answers

2
LuLuGaGa On

For shapes a good approach would be to combine overlay and offset like so:

Rectangle()
    .fill(Color.red)
    .frame(width: 100, height: 180)
    .overlay(
        Circle()
            .fill(Color.blue.opacity(0.5))
            .frame(width: 100)
            .offset(y: -90)
    )

enter image description here

0
Asperi On

Here is possible approach - just to use alignment without hardcoding offsets/positions.

Demo prepared with Xcode 12.4 / iOS 14.4

var body: some View {
    Rectangle()
        .fill(Color.gray)
        .frame(width: 85, height: 175)
        .overlay(
            Circle()
              .stroke(Color.black,
                    style: StrokeStyle(
                         lineWidth: 2,
                         lineCap: .round,
                         lineJoin: .miter,
                         miterLimit: 0,
                         dash: [5, 10],
                         dashPhase: 0
                    ))
              .frame(width: 85, height: 85)
              .alignmentGuide(.top) { $0[VerticalAlignment.center] } // << this !!
        , alignment: .top)    // and this !!
}

demo