🎉

SwiftUIでいい感じのScrollViewを作ってみる

2023/08/04に公開

前書き

最近、X(前Twitter)でボトムナビゲーションが急に非表示になって困惑していたNaoRandDです😇

この記事では、SwiftUIGeometryReaderrotation3DEffectを活用して、水平方向にスクロール可能なコンテンツを持つAwesomeScrollView(仮称😇)を作成する方法を紹介します

GeometryReaderは、ビューの幅や高さなどのジオメトリ情報を取得するための便利なビューです。これを使って、スクロール時のアニメーションや要素の配置を調整します

Image from Gyazo

GeometryReaderとは?

GeometryReaderは、SwiftUIで提供されるビューの一つであり、内部に配置されたビューのジオメトリ情報(位置、サイズなど)を取得できるコンテナビューです
これを利用することで、親ビューのサイズに応じて自動的にサイズを調整したり、特定の条件に基づいてビューを動的に変更したりすることができます

https://developer.apple.com/documentation/swiftui/geometryreader

今回はrotation3DEffectを組み合わせて、スクロールに応じてViewを3Dに回転させるようにしてみようかと思います
https://developer.apple.com/documentation/swiftui/view/rotation3deffect(_:axis:anchor:anchorz:perspective:)

流れ

  1. AwesomeScrollViewは、ジオメトリ情報を取得するためのGeometryReader内にHStackを持つScrollViewとして定義されています。
  2. ScrollViewは、水平方向にスクロールするように指定されています。
  3. HStack内でForEachループを使い、sections配列内の各セクションデータをGeometryReader内に配置します。
  4. GeometryReaderの中では、makeSection関数を呼び出して、各セクションのビューを作成します。セクションのビューはジオメトリ情報に基づいたアニメーションを持ちます。

実装コード

AwesomeScrollViewの実装は下記のような感じです

import SwiftUI

struct AwesomeScrollView: View {

    // ・・・ Sectionのデータ情報など

    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 20) {
                ForEach(sections) { section in
                    // GeometryReaderを使ってセクションを配置
                    GeometryReader { geometry in
                        makeSection(section: section)
                            .rotation3DEffect(
                                Angle(
                                    degrees: Double(geometry.frame(in: .global).minX - 30) / -20),
                                    axis: (x: 0, y: 1, z: 0))
                    }
                    .frame(width: 275, height: 275)
                }
            }
            .padding(30)
            .padding(.bottom, 30)
        }
    }

    // セクションのビューを作成する関数
    @ViewBuilder
    func makeSection(section: Section) -> some View {
        VStack {
            HStack(alignment: .top) {
                Text(section.title)
                    .font(.system(size: 24, weight: .bold))
                    .frame(width: 160, alignment: .leading)
                    .foregroundColor(.white)
                Spacer()
                section.logo
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: 50, height: 50)
            }

            Text(section.text)
                .font(.system(size: 15, weight: .bold))
                .frame(maxWidth: .infinity, alignment: .leading)

            section.image
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(width: 210)
        }
        .padding(.top, 20)
        .padding(.horizontal, 20)
        .frame(width: 275, height: 275)
        .background(section.color)
        .cornerRadius(30)
        .shadow(color: section.color.opacity(0.3), radius: 20, x: 0, y: 20)
    }
}

まとめ

SwiftUIのGeometryReaderを使って、スクロール可能なコンテンツを持つAwesomeScrollViewを作成する方法について学びました!
ジオメトリ情報を活用することで、動的なアニメーションやビューの配置を実現できるため、柔軟なUIの構築が可能となります

コードは下記においています🙋‍♀️(適宜ご参照ください)
https://github.com/Nao-RandD/AwesomeScrollView

あとがき

SwiftUIのパワフルな機能を活用して、より魅力的なユーザーエクスペリエンスを持つアプリを開発してみてください!


参考

Discussion