SwiftUI | 如果被 ScrollView 取消,则不会调用 DragGestures onEnded

Mof*_*waw 7 ios swift swiftui

我有以下问题。

我有一个View内部的ScrollView,我想拖。现在,一切正常,发生拖动和滚动。但是,一旦我尝试同时执行这两项操作,dragOffset似乎就会停留,而不是重置到其初始位置。

更何况,onEndedDragGesture永远不会发生。我怎样才能阻止这种情况发生并将绿色重置Rectangle到其初始位置?

视觉表现

拖动或滚动工作得很好。

但是每当我同时做这件事时,就会发生这种情况。

演示代码

struct ContentView: View {
    
    @State private var dragOffset: CGSize = .zero
    
    
    var body: some View {
        ScrollView {
            Rectangle()
                .frame(width: UIScreen.main.bounds.size.width, height: 300)
                .foregroundColor(.green)
                .offset(x: dragOffset.width)
        }
        .gesture(DragGesture()
            .onChanged { value in
                dragOffset = value.translation
            }
            .onEnded { value in
                dragOffset = .zero
            }
        )
        .animation(.default)
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

Mof*_*waw 5

解决方案是使用.updatingwithGestureState代替。无论出于何种原因取消手势后,它都会自动将偏移设置为其初始位置。

这样,我们独立于调用onEnded将其设置为初始位置,当您通过滚动取消手势时不会发生这种情况。

代码:

struct ContentView: View {
    
    @GestureState private var dragOffset: CGSize = .zero
    
    
    var body: some View {
        ScrollView {
            Rectangle()
                .frame(width: UIScreen.main.bounds.size.width, height: 300)
                .foregroundColor(.green)
                .offset(x: dragOffset.width)
        }
        .gesture(DragGesture()
            .updating($dragOffset) { value, state, transaction in
                state = value.translation
            }
        )
        .animation(.default)
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:当然你仍然可以有一个onChangedonEnded块,你只是不必再设置偏移量,.zero因为它会自动发生。

更新

如果您要在ObservableObject课堂上使用它并希望发布您的 dragOffset,那么这将是我找到的解决方案

  • 我担心,无论您添加哪种策略,ScrollView 仍然会在启动时立即取消任何拖动手势。因此,“更新”将被调用一次,然后手势将被取消并且不再被调用。 (5认同)