onAppearで表示してもタイミング的にだめな時ってあるよね。今回は、遷移した際で、特定位置を画面の上部にスクロールさせてから、表示したかったのだが、移動するのが見えてしまうので、その対応策をメモしておきます

時間を少しあけてから、画面を表示というより見えるようにする

今回やりたいのは以下のような感じ。

前提として、遷移先にはtwitterのタイムラインのようにアイテムが並んでいて、
特定のアイテムが画面上部にきた状態で遷移したい。

ところが、ScrollViewReaderで移動させたとしても、遷移した直後に遷移させると、
他がレンダリングできていない状態なので、思った場所にスクロールしてくれない。

なので、scrollを0.2秒遅延させて実行すると、位置はいいが、遷移した後、最初に通常の場所で表示され、0.1秒後に希望の場所に移動してると、大変ださいことになっている。

@State private var isReady = false

var body: some View {
    ScrollViewReader { proxy in
        ScrollView {
            VStack {
                ForEach(items, id: \.self) { item in
                    Text("Item \(item)")
                        .id(item)
                        .opacity(isReady ? 1 : 0) // 初期は非表示
                }
            }
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                proxy.scrollTo(items.last, anchor: .top)
                isReady = true // 完全にスクロールした後に表示
            }
        }
    }
}

ひとまず、0.1秒後にスクロールさせるので、位置は問題ない。

ただ、表示タイミングに問題があるので、スクロールを実行した後、
画面を透明から表示にさせるよう、opacityで制御する。

これで、遷移した後の画面がぱっと表示されるようになった

よかったね

コメント