最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - How to prevent section header from inheriting shadow of List view? - Stack Overflow

programmeradmin1浏览0评论

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 to PlainListStyle or DefaultListStyle 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 to PlainListStyle or DefaultListStyle 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
Add a comment  | 

1 Answer 1

Reset to default 0

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.
  • 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
                )
        }
    }
}

发布评论

评论列表(0)

  1. 暂无评论