📝

[SwiftUI] ScrollViewでshadowが見切れてしまうの大変じゃないですか?

2023/03/20に公開

概要

SwiftUIでよくあるScrollViewにクリップがきいてしまって、影が見切れてしまう。。。

struct ContentView: View {
    var body: some View {
        ScrollView(showsIndicators: false) {
            Spacer().frame(height: 200)
            ScrollView(.horizontal, showsIndicators: false) {
                LazyHStack(alignment: .top, spacing: 8) {
                    ForEach(0..<8, id: \.self) { index in
                        Text("Hello, world!")
                            .frame(height: 50)
                            .foregroundColor(.white)
                            .background(.red)
                            .shadow(color: .black, radius: 10, x: 0, y: 3)
                            .id(index)
                    }
                }
            }
        }
    }
}

よくある実装

普通にLazyHStackにpaddingつけたらいい。

struct ContentView: View {
    var body: some View {
        ScrollView(showsIndicators: false) {
            Spacer().frame(height: 200)
            ScrollView(.horizontal, showsIndicators: false) {
                LazyHStack(alignment: .top, spacing: 8) {
                    ForEach(0..<8, id: \.self) { index in
                        Text("Hello, world!")
                            .frame(height: 50)
                            .foregroundColor(.white)
                            .background(.red)
                            .shadow(color: .black, radius: 10, x: 0, y: 3)
                            .id(index)
                    }
                }
                .padding() // 追加
            }
        }
    }
}

けど、これやと、余白がついて影が表示されるが、これだと余白の管理が複雑になってくる。。。

解決

clipsToBoundsいじって切り取られやんようにしたらええんや

extension UIScrollView {
  open override var clipsToBounds: Bool {
    get { false }
    set { }
  }
}
struct ContentView: View {
    var body: some View {
        ScrollView(showsIndicators: false) {
            Spacer().frame(height: 200)
            ScrollView(.horizontal, showsIndicators: false) {
                LazyHStack(alignment: .top, spacing: 8) {
                    ForEach(0..<8, id: \.self) { index in
                        Text("Hello, world!")
                            .frame(height: 50)
                            .foregroundColor(.white)
                            .background(.red)
                            .shadow(color: .black, radius: 10, x: 0, y: 3)
                            .id(index)
                    }
                }
            }
        }
    }
}

import UIKit

extension UIScrollView {
  open override var clipsToBounds: Bool {
    get { false }
    set { }
  }
}

Discussion