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:
- adding the List formatting to a
positeGroup()
and then applying the shadow- This had no effect
- Setting
.textCase()
of the SectionHeader to.none
- this removed all text formatting, but not the shadow from the text
- Creating a custom
View
for the section header with its own formatting- This view still inherited the shadow
- Adding the shadow to the row view itself
- This gave all text in the row the shadow, but not the row view
- This also continued to be true when applying after a
compositeGroup
on the view - The shadow did disappear from the Section text however
- Adding the shadow in the row class to the
HStack
the elements are contained in- Same effect as above
- Removing the Section all together and making a
Text
view instead- This view still inherited the shadow
- Setting the
.listStyle
toPlainListStyle
orDefaultListStyle
per this SO thread- had no effect, changed row width
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
}
}
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:
- adding the List formatting to a
.compositeGroup()
and then applying the shadow- This had no effect
- Setting
.textCase()
of the SectionHeader to.none
- this removed all text formatting, but not the shadow from the text
- Creating a custom
View
for the section header with its own formatting- This view still inherited the shadow
- Adding the shadow to the row view itself
- This gave all text in the row the shadow, but not the row view
- This also continued to be true when applying after a
compositeGroup
on the view - The shadow did disappear from the Section text however
- Adding the shadow in the row class to the
HStack
the elements are contained in- Same effect as above
- Removing the Section all together and making a
Text
view instead- This view still inherited the shadow
- Setting the
.listStyle
toPlainListStyle
orDefaultListStyle
per this SO thread- had no effect, changed row width
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
}
}
Share
Improve this question
edited Feb 8 at 10:03
Mark Rotteveel
109k226 gold badges155 silver badges219 bronze badges
asked Feb 7 at 21:33
TestinginProdTestinginProd
1,1561 gold badge17 silver badges37 bronze badges
2
- Do you mean like the commented code in the first if statement? – TestinginProd Commented Feb 7 at 22:45
- 1 Good call. I replaced the code with a minimum reproducible example – TestinginProd Commented Feb 7 at 23:57
1 Answer
Reset to default 0If 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 ifanchor: .bottom
is used.- Alternatively, the overlay could be applied with
alignment: .topLeading
and padding used to adjust its position. - To mimic the styling, set the font to
.subheadline.smallCaps()
. - If you really want to match the styling precisely, you may need to tweak the kerning too.
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
)
}
}
}