【SwiftUI】ビューコントローラー:ScrollView

環境

Xcode16.1
Swift:6
iOS16

基本

概要

ScrollViewとは
方向(縦、横、全方位)を指定してスクロールができるビュー。
ScrollViewはデータ要素を10個までしか置くことができないため
要素が多くなる場合はForEachを使用する。
Listと違い、すぐにインスタンスを作成するため大量表示する場合は要注意。

引数

スクロール方向:縦:.vertical(デフォルト)、横:.horizontal
showsIndicators:スクロールバーの表示を制御(true:表示(デフォルト)、false:非表示)

ScrollView {
    // スクロール表示するビュー
}

縦方向のスクロール

import SwiftUI

struct ContentView: View {

    var body: some View {
        ScrollView {

            ForEach(1..<100) { index in
                Text("\(index) 行目").font(.title)
            }
        }
    }
}

#Preview {
    ContentView()
}

横方向のスクロール

HStackを使用するのと、.horizontalを指定するのがポイント

import SwiftUI

struct ContentView: View {

    var body: some View {
        ScrollView(.horizontal) {
            HStack {
                ForEach(1..<100) { index in
                    Text("データ\(index)")
                }
            }
        }

    }
}

#Preview {
    ContentView()
}

スクロールバーを非表示にする(showsIndicators)

showsIndicators: falseを指定する

import SwiftUI

struct ContentView: View {

    var body: some View {
        ScrollView(showsIndicators: false) {
            ForEach(1..<100) { index in
                Text("データ\(index)")
            }
        }
    }
}

#Preview {
    ContentView()
}

スクロール位置を指定する(ScrollViewReader)

引数

id:スクロールして表示させるビューのIDを指定
anchor:どこの位置までスクロールするか指定。省略時は対象の要素全体が見えるように最小量だけスクロールされる

scrollTo(id, anchor: UnitPoint)

【anchorの代表的な値】

.top
.center 中央
.bottom
.leading
.trailing

import SwiftUI

struct ContentView: View {

    var body: some View {
        ScrollViewReader { scrollProxy in       // ①ScrollViewProxyインスタンスを取得
            VStack {
                ScrollView {
                    VStack {
                        ForEach(1..<100) {
                            Text("\($0) 行目")
                                .id($0)         // ②スクロール先を指定する為の一意のIDを指定
                        }
                    }
                }
                Button("50行目に飛ぶ"){
                    withAnimation {
                        // ③scrollToメソッドで飛び先を指定
                        scrollProxy.scrollTo(50, anchor: .center)
                    }
                }
            }
        }
    }
}

#Preview {
    ContentView()
}