首页 > 解决方案 > 如何在 SwiftUI 中读取 ScrollView 中的拖动位置?

问题描述

我正在尝试读取连接到 ScrollView 的视图的 DragGesture 中的位置,但 ScrollView 控制所有视图上的 DragGesture 并且不允许我阅读这些信息。这是我展示问题的示例, 我的目标是读取 DragGesture 中的拖动位置。

使用新代码:

    struct ContentView: View {
    
    @State var locationY: CGFloat = .zero
    
    var body: some View {
        
        VStack
        {
            
            
            
            HStack
            {
                
                
                VStack
                {
                    Color.black.frame(height: 300)
                }
                .gesture( DragGesture().onChanged { value in locationY = value.location.y; print(locationY)} )
                
                
                
                
                ScrollView
                {
                    VStack
                    {
                        Color.blue.frame(height: 300)
                    }.background(GeometryReader {
                        Color.clear.preference(key: ViewOffsetKey.self,
                                               value: $0.frame(in: .global).origin.y)
                        // value: $0.frame(in: .named("scroll_area")).origin.y)
                    })
                }
                // .coordinateSpace(name: "scroll_area")
                .onPreferenceChange(ViewOffsetKey.self) {
                    self.locationY = $0
                    print(">> offset: \($0)")
                }
                .frame(height: 300)
                
                
            }
            
            Spacer()
            
        }
        
        
        
        
    }
}



struct ViewOffsetKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

标签: swiftui

解决方案


这是可能的解决方案,用于GeometryReader在后台读取视图矩形(在任何需要的坐标空间中)和视图首选项以在顶层传递所需的坐标。

使用 Xcode 12.1 / iOS 14.1 测试

注意:注释变体用于超级视图(即 ScrollView)坐标

    ScrollView
    {
        VStack
        {
            Color.blue.frame(height: 300)
             }.background(GeometryReader {
                  Color.clear.preference(key: ViewOffsetKey.self,
                        value: $0.frame(in: .global).origin.y)
                        // value: $0.frame(in: .named("scroll_area")).origin.y)
             })
    }
    // .coordinateSpace(name: "scroll_area")
         .onPreferenceChange(ViewOffsetKey.self) {
            self.locationY = $0
            print(">> offset: \($0)")
        }

和助手偏好键

struct ViewOffsetKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

推荐阅读