簡體   English   中英

SwiftUI 中 DragGesture 和 ScrollView 的交互

[英]Interaction of DragGesture and ScrollView in SwiftUI

在我正在開發的應用程序中,有一部分主要是“前進”導航——點擊按鈕將顯示下一張幻燈片。 然而,輔助“向后”導航也是必要的。 這是我使用的方法:

import SwiftUI

struct Sample: View {
    @State private var dragOffset: CGFloat = -100
    var body: some View {
        VStack {

            Text("Perhaps a title")

            ScrollView {
                VStack {
                    Text("Some scrollable content is going to be here")

                    // ...

                    Button(action: {
                        // Go to the next slide
                    }) { Text("Next") }
                }
            }

            Text("and, maybe, something else")
        }
        .overlay(
            Image(systemName: "arrow.left").offset(x: dragOffset / 2),
            alignment: .leading
        )
        .gesture(
            DragGesture()
                .onChanged{
                    self.dragOffset = $0.translation.width
                }
                .onEnded {
                    self.dragOffset = -100 // Hide the arrow

                    if $0.translation.width > 100 {
                        // Go to the previous slide
                    }
                }
        )
    }
}

有一個小指標(左箭頭),最初是隱藏的(dragOffset = -100)。 當拖動手勢開始時,偏移量被輸入到dragOffset狀態變量中,並且有效地顯示箭頭。 當拖動手勢結束時,箭頭再次隱藏,如果達到某個偏移量,則顯示上一張幻燈片。

工作得很好,除了當用戶滾動 ScrollView 中的內容時,這個手勢也會被觸發並更新一段時間,但我認為,它被 ScrollView 取消並且不調用“onEnded”。 結果,箭頭指示符停留在屏幕上。

因此,問題是:做這樣的手勢的正確方法是什么,可以與 ScrollView 一起使用? SwiftUI 的當前狀態是否有可能?

對於這種臨時狀態,最好使用GestureState ,因為它會在手勢取消/完成后自動重置為初始狀態。

所以這是可能的方法

更新:使用 Xcode 13.4 / iOS 15.5 重新測試

演示:

在此處輸入圖像描述

代碼:

struct Sample: View {
    @GestureState private var dragOffset: CGFloat = -100
    var body: some View {
        VStack {

            Text("Perhaps a title")

            ScrollView {
                VStack {
                    Text("Some scrollable content is going to be here")

                    // ...

                    Button(action: {
                        // Go to the next slide
                    }) { Text("Next") }
                }
            }

            Text("and, maybe, something else")
        }
        .overlay(
            Image(systemName: "arrow.left").offset(x: dragOffset / 2),
            alignment: .leading
        )
        .gesture(
            DragGesture()
                .updating($dragOffset) { (value, gestureState, transaction) in
                    let delta = value.location.x - value.startLocation.x
                    if delta > 10 { // << some appropriate horizontal threshold here
                        gestureState = delta
                    }
                }
                .onEnded {
                    if $0.translation.width > 100 {
                        // Go to the previous slide
                    }
                }
        )
    }
}

注意: dragOffset: CGFloat = -100這可能對不同的真實設備有不同的影響,所以可能最好明確計算。

備份

如果您不想使用@GestureState也可以使用DragGesture(minimumDistance: 0.0) 這讓 DragGesture 在滾動手勢被激活之前啟動。 雖然這對我來說似乎是蘋果的一個錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM