I have added a VStack, I am adding 3 elements like Top , middle and bottom and adding shadow respectively. Problem is I am getting 1px gap between the elements even after adding spacing as 0. Top element will have traling , leading and bottom shadow Middle will have only leading and traling shadow Bottom will have leading, trailing and bottom shadow. I have tried adding offset its not improving
struct ContentView: View {
var body: some View {
VStack(spacing: 0) {
Text("Test")
.padding()
.background(
Color.white
.clipShape(
.rect(topLeadingRadius: 12, bottomLeadingRadius: 0, bottomTrailingRadius: 0, topTrailingRadius: 12)
)
)
.shadow(color: .black.opacity(0.5), radius: 5)
.addShadow(topPadding: -30, bottomPadding: 0, trailingPadding: -30, leadingPadding: -30)
Text("Test")
.padding()
.background(
Color.white
.clipShape(
.rect(topLeadingRadius: -2, bottomLeadingRadius: -2, bottomTrailingRadius: -2, topTrailingRadius: -2)
)
)
.offset(x: 0, y: -1)
.shadow(color: .black.opacity(0.5), radius: 5)
.addShadow(topPadding: 0, bottomPadding: 0, trailingPadding: -30, leadingPadding: -30)
Text("Test")
.padding()
.background(
Color.white
.clipShape(
.rect(topLeadingRadius: 0, bottomLeadingRadius: 2, bottomTrailingRadius: 2, topTrailingRadius: 0)
)
)
[enter image description here](https://i.sstatic.net/2dRrCOM6.png) .shadow(color: .black.opacity(0.5), radius: 5)
.addShadow(topPadding: 0, bottomPadding: -30, trailingPadding: -30, leadingPadding: -30)
}
}
}
struct MaskModifier: ViewModifier {
let topPadding: CGFloat
let bottomPadding: CGFloat
let trailingPadding: CGFloat
let leadingPadding: CGFloat
init(
topPadding: CGFloat,
bottomPadding: CGFloat,
trailingPadding: CGFloat,
leadingPadding: CGFloat
) {
self.topPadding = topPadding
self.bottomPadding = bottomPadding
self.trailingPadding = trailingPadding
self.leadingPadding = leadingPadding
}
func body(content: Content) -> some View {
content
.mask(
Rectangle()
.padding(.top, topPadding)
.padding(.leading, leadingPadding)
.padding(.trailing, trailingPadding)
.padding(.bottom, bottomPadding)
)
}
}
extension View {
func addShadow(topPadding: CGFloat,
bottomPadding: CGFloat,
trailingPadding: CGFloat,
leadingPadding: CGFloat) -> some View {
modifier(MaskModifier(topPadding: topPadding, bottomPadding: bottomPadding, trailingPadding: trailingPadding, leadingPadding: leadingPadding))
}
}
Try moving the shadow to the background of each view and removing the offset:
VStack(spacing: 0) {
Text("Test")
.padding()
.background(
Color.white
.clipShape(
.rect(topLeadingRadius: 12, bottomLeadingRadius: 0, bottomTrailingRadius: 0, topTrailingRadius: 12)
)
.shadow(color: .black.opacity(0.5), radius: 5)
.addShadow(topPadding: -30, bottomPadding: 0, trailingPadding: -30, leadingPadding: -30)
)
// ...etc
}
You will notice that the shadow drops between each section. This is because, there is less shadow around the corners of each child shape.
To compensate, you could add negative padding before adding the shadows. The masks that you are already using will take care of clipping the extended shadows. The extra clip shape on the middle section is not needed:
Text("Test")
.padding()
.background {
Color.white
.clipShape(
.rect(topLeadingRadius: 12, bottomLeadingRadius: 0, bottomTrailingRadius: 0, topTrailingRadius: 12)
)
.padding(.bottom, -30)
.shadow(color: .black.opacity(0.5), radius: 5)
.addShadow(topPadding: -30, bottomPadding: 0, trailingPadding: -30, leadingPadding: -30)
}
Text("Test")
.padding()
.background {
Color.white
.padding(.vertical, -30)
.shadow(color: .black.opacity(0.5), radius: 5)
.addShadow(topPadding: 0, bottomPadding: 0, trailingPadding: -30, leadingPadding: -30)
}
Text("Test")
.padding()
.background {
Color.white
.clipShape(
.rect(topLeadingRadius: 0, bottomLeadingRadius: 2, bottomTrailingRadius: 2, topTrailingRadius: 0)
)
.padding(.top, -30)
.shadow(color: .black.opacity(0.5), radius: 5)
.addShadow(topPadding: 0, bottomPadding: -30, trailingPadding: -30, leadingPadding: -30)
}
However, this would seem to be a rather convoluted way of adding a shadow around a group of items inside a container. A simpler and cleaner approach would be to move the background and its shadow to the container itself (the VStack
). Then you don't need to use a mask to clip the different parts of the shadow:
VStack(spacing: 0) {
Text("Test")
.padding()
Text("Test")
.padding()
Text("Test")
.padding()
}
.background {
Color.white
.clipShape(
.rect(topLeadingRadius: 12, bottomLeadingRadius: 2, bottomTrailingRadius: 2, topTrailingRadius: 12)
)
.shadow(color: .black.opacity(0.5), radius: 5)
}