9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SwiftUI コードで一番下まで自動的にスクロールさせる

Last updated at Posted at 2021-05-30

この方の記事が参考になりました。
https://qiita.com/chocoyama/items/b775e80e445d81d33814

私の場合は、コードで自動的に(ユーザー操作なしで)一番下までスクロールさせようとして悩みました。
探してもなかなか引っ掛からなかったので検索の助けになれば幸いです。

コードでスクロールさせる方法

コードでスクロールさせるためには ScrollViewReaderscrollTo を使います。
タイミングを自由にコントロールするために onChange も使います。

イメージ.swift
ScrollViewReader {

    ...
    ScrollView {} // ここにスクロールさせたい View を挟む
    ...

    .onChange() {
        .scrollTo()
    }
}

コード例

ポイント

  • View の中に @StateObject として コントロールする側のクラスXXXを 持っておく

    • @StateObject var xxx = XXX()
  • クラスXXXの中に @Published な 変数scrollIDを持っておく

    • @Published var scrollID: Int = 0
  • スクロールして表示させたいViewに id(...) をつけておく

    • 今回は一番下のViewに付ける id(999)
  • スクロールするView本体(ScrollView)に .onChange(...) をつけておく。

    • .onChange(of: xxx.scrollID) { id in ... }
  • ScrollViewを ScrollViewReader {...} で挟む

    • ScrollViewReader { proxy in ... }
  • onChange(...)の中に scrollTo(...) を書く

    • proxy.scrollTo(id)
  • scrollID が変更された時に自動的にスクロールする

    • self.scrollID = 999
Sample.swift
import SwiftUI

struct ContentView: View {
    @StateObject var xxx = XXX()
    
    var body: some View {
        
        ScrollViewReader { proxy in
            ScrollView {
                VStack {
                    Text("A")
                    Text("B")
                    Text("C")
                    Text("D")
                    Text("E")
                    Text("F")
                    Text("G")
                    Text("H")
                    Text("I")
                    Text("J").id(999)
                }
                .onAppear {
                    // 表示されたことを xxx に知らせる
                    self.xxx.onAppear()
                }
            }
            .onChange(of: xxx.scrollID) { id in
                withAnimation {
                    proxy.scrollTo(id)
                }
            }
        }
    }
}

class XXX: ObservableObject {
    @Published var scrollID: Int = 0
    
    func onAppear() {
        // 表示された 3 秒後に scrollID を 999 に変更する
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            self.scrollID = 999
        }
    }
}

※ 初めの動画ではこのコードに加えて、わかりやすくするために色をつけたり高さを調整しています。

おまけ

  • withAnimation { ... } を書かなければ、アニメーションなしで一瞬でスクロールできます。
  • scrollTo(id) の代わりに scrollTo(id, anchor: ...) を使えば、スクロールしたあとのViewの位置を細かく調整できます。

以上です。
ありがとうございました。

9
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?