CatHand Blog

アプリ開発やMac弄り

SwiftUIで影が切れる

横スクロールで要素が並んでるようなUIを考えます。

struct TestView: View {
    
    var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            Text("上の要素")
                .padding(.bottom, 10)
            ScrollView(.horizontal, showsIndicators: true) {
                HStack(spacing: 20) {
                    Spacer()
                        .frame(width: 0, height: 0)
                    Item()
                    Item()
                    Item()
                    Item()
                    Item()
                    Spacer()
                        .frame(width: 0, height: 0)
                }
            }
            Text("下の要素")
        }
    }
}

struct Item: View {
    
    var body: some View {
        Color(.blue)
            .frame(width: 100, height: 100)
            .shadow(color: Color(R.color.shadow()!), radius: 18, x: 0, y: 4)
    }
}

こんなかんじで、各要素には影が付いています。

これを実行すると

f:id:cathandnya:20200410125348p:plain
影が切れる

少し見づらいですが、影が切れています。

どうやら影は ScrollViewクリッピングされてしまうようです。

これを解決するには、padding を入れて offset します。

struct TestView: View {
    
    var body: some View {
        VStack(alignment: .leading, spacing: 0) {
            Text("上の要素")
                .padding(.bottom, 10)
            ScrollView(.horizontal, showsIndicators: true) {
                HStack(spacing: 20) {
                    Spacer()
                        .frame(width: 0, height: 0)
                    Item()
                    Item()
                    Item()
                    Item()
                    Item()
                    Spacer()
                        .frame(width: 0, height: 0)
                }
                    .padding(.top, 30)    // 影が入りそうなくらいpaddingいれる
                    .padding(.bottom, 30)
            }
                .offset(y: -30)    // padding分offset
                .padding(.bottom, 10)
            Text("下の要素")
                .offset(y: -60)    // padding分offset
        }
    }
}

f:id:cathandnya:20200410125720p:plain
影が切れない

だいぶバッドノウハウ感ありますが、とりあえずこれで解決できます。