I am trying to offset an image to make a nice profile view but the image is cut-off as shown in the image below:
and below is the code:
NavigationStack {
ScrollView(.vertical) {
Section() {
VStack() {
Image("dflt_profile_img")
.resizable()
.frame(width: /*@START_MENU_TOKEN@*/100/*@END_MENU_TOKEN@*/, height: 100)
.clipShape(RoundedRectangle(cornerRadius: /*@START_MENU_TOKEN@*/25.0/*@END_MENU_TOKEN@*/))
.padding(12)
.offset(y: -50.0)
}
.frame(maxWidth: /*@START_MENU_TOKEN@*/.infinity/*@END_MENU_TOKEN@*/)
.background(Color.cOrange.opacity(0.25))
.clipShape(RoundedRectangle(cornerRadius: 25.0))
.padding([.leading, .trailing], 24)
.padding(.top, 50)
}
}
Any idea how to have the profile image not cut-off but still position on top of the stack aligned in the middle of the image.
The image is being clipped because you applied .clipShape
on the VStack
. As its name suggests, clipShape
clips the contents of the view.
You can use background(_:in:)
to apply a background to only a specific region of the view, as determined by a Shape
.
VStack() {
Image("my_image")
.resizable()
.frame(width: 100, height: 100)
.clipShape(RoundedRectangle(cornerRadius: 25.0))
.padding(12)
.offset(y: -50.0)
}
.frame(maxWidth: .infinity)
// here!
.background(.orange.opacity(0.25), in: RoundedRectangle(cornerRadius: 25.0))
.padding(.horizontal, 24)
.padding(.top, 50)
I would suggest using a ZStack
with alignment: .top
as container for the VStack
and the image. This way, you just need to apply top padding to the VStack
(which you were doing already), the offset on the image can be removed.
Section() {
ZStack(alignment: .top) {
VStack {
// ...main content
}
.frame(maxWidth: .infinity, minHeight: 100)
.background(Color.orange.opacity(0.25))
.clipShape(RoundedRectangle(cornerRadius: 25.0))
.padding([.leading, .trailing], 24)
.padding(.top, 50)
Image("dflt_profile_img")
.resizable()
.frame(width: 100, height: 100)
.clipShape(RoundedRectangle(cornerRadius: 25.0))
.padding(12)
}
}