Reputation: 1166
I have a SwiftUI List
where each row has a shadow under it, to add a 3D look to it. While the rows look great, the section header text seems to inherit the shadow from the list, and nothing I have tried can remove it.
Screenshot of the effect based on code below:
What I have tried so far:
.compositeGroup()
and then applying the shadow
.textCase()
of the SectionHeader to .none
View
for the section header with its own formatting
compositeGroup
on the viewHStack
the elements are contained in
Text
view instead
.listStyle
to PlainListStyle
or DefaultListStyle
per this SO thread
I'm at a total loss on what to do.
How do I make the Section
text not inherit the shadow formatting on the List
view?
Minimal reproducible example:
struct MinReproduceExample: View {
var body: some View {
List {
Section(header: MinReproCell(text: "Section Title")) {
MinReproCell(text: "Cell text")
//causes shadow on cell text
//does not create red shadow on cell view itself
.shadow(color:.red, radius: 5, x:-3, y:3)
}
}
.background(.clear)
//Must be here to make cell view shadow red.
//Also causes Section title to be red
//does not cause cell text to have red shadow
.shadow(color:.red, radius: 5, x:-3, y:3)
//scrollContent required to be clear to show shadows of views
.scrollContentBackground(.hidden)
}
}
struct MinReproCell: View {
var text: String
var body: some View {
Text(text).foregroundStyle(.black)
}
}
struct MinReproSection:View {
var text: String
var body: some View {
Text(text)
.foregroundStyle(.black)
.font(Font.system(size: 20, weight: .bold))
.textCase(.none) // has no effect on section text shadow
}
}
Upvotes: 0
Views: 55
Reputation: 21710
If the .shadow
is applied to the List
as a whole then it is going to apply to all the content inside the list. This includes the section header.
One workaround would be to apply the shadow effect to the list rows instead. This is demonstrated in the answer to How to use dual shadows on a list? (it was my answer). However, this technique is a bit cumbersome.
A simpler workaround is to hide the native section header and show your own header as an overlay in the same space:
.matchedGeometryEffect
can be used to match the position exactly. I found it works best if anchor: .bottom
is used.alignment: .topLeading
and padding used to adjust its position..subheadline.smallCaps()
.struct MinReproduceExample: View {
@Namespace private var ns
var body: some View {
List {
Section {
MinReproCell(text: "Row one")
MinReproCell(text: "Row two")
.shadow(color:.red, radius: 5, x:-3, y:3)
} header: {
MinReproCell(text: "Section Title")
.hidden()
.matchedGeometryEffect(id: "title", in: ns, anchor: .bottom)
}
}
.background(.clear)
.scrollContentBackground(.hidden)
.shadow(color:.red, radius: 5, x:-3, y:3)
.overlay {
MinReproCell(text: "Section Title")
.font(.subheadline.smallCaps())
.kerning(0.2)
.matchedGeometryEffect(
id: "title",
in: ns,
properties: .position,
anchor: .bottom,
isSource: false
)
}
}
}
Upvotes: 0