【问题标题】:How to enable multiple gestures?如何启用多个手势?
【发布时间】:2020-08-13 07:48:48
【问题描述】:

我创建了一个由主视图组成的应用程序,其中有多个视图,每个形状一个。对于形状,我想启用一些交互,以便在点击时转换其属性。由于转换也取决于点击位置,因此我通过以下方式将其实现为 DragGesture:

.gesture(DragGesture(minimumDistance: 0, coordinateSpace: .global)
.onChanged { gesture in
      print("Tap location: \(gesture.startLocation)")    
           })

除了单个形状的转换之外,我还希望用户能够拖动整个内容和/或调整其大小。因此,在主视图中,我实现了拖动手势和放大手势。由于点击和拖动是冲突的,我添加了一个选项来切换点击和拖动之间的交互模式。通过检查形状视图内的以下条件来启用/禁用转换:

.allowsHitTesting(dragGestureMode == DragGestureEnum.TransformShape)

尽管如此,有时当我尝试调整图像大小时,该手势被解释为某个形状上的拖动手势,该手势执行在该形状上点击(以最小距离 0 拖动)而不是调整大小(在拖动的情况下)的逻辑模式这不是问题)。

以下是主视图的逻辑和放置在主视图中的实例的形状视图:

struct MainView: View {
    @EnvironmentObject var mainViewModel : MainViewModel
    @State private var offset = CGSize.zero
    @State private var draggedSize: CGSize = CGSize.zero
    @State private var scale: CGFloat = 1.0
    @State private var scaledSize: CGFloat = 1.0
    var body: some View {
        GeometryReader {
            geometry in
            ZStack {
                ForEach(mainViewModel.shapeItemKeys, id: \.self){ id in
                    let shapeItem = $mainViewModel.shapeItemsByKey[id]
                    ShapeView(shapeItem: shapeItem, dragGestureMode: $mainViewModel.dragGestureMode)
                }
            }
            .frame(width: min(geometry.size.width, geometry.size.height), height: min(geometry.size.width, geometry.size.height), alignment: .center)
            .contentShape(Rectangle())
            .offset(x: self.draggedSize.width, y: self.draggedSize.height)
            .scaleEffect(self.scaledSize)
            .gesture(
                DragGesture()
                    .onChanged { gesture in
                        self.draggedSize = gesture.translation
                        self.draggedSize.width += self.offset.width
                        self.draggedSize.height += self.offset.height
                        
                    }

                    .onEnded { _ in
                        self.offset = self.draggedSize
                    }
            )
            .gesture(MagnificationGesture()
                        .onChanged({ (scale) in
                            self.scaledSize = scale.magnitude
                            self.scaledSize *= self.scale
                        })
                        .onEnded({ (scaleFinal) in
                            self.scale = scaleFinal
                            print("New scale: \(self.scale)")
                            self.scale = self.scaledSize
                        }))
 
        }
    }
}


struct ShapeView: View {
    @Binding var shapeItem: ShapeItem?
    @Binding var dragGestureMode: DragGestureEnum
    var layersToRemove: [Int] = []
    init(shapeItem: Binding<ShapeItem?>, dragGestureMode: Binding<DragGestureEnum>) {
        self._shapeItem = shapeItem
        self._dragGestureMode = dragGestureMode
    }
    var body: some View {
        ZStack {
            shapeItem!.path
                .foregroundColor(Color(shapeItem!.color))
                .overlay(
                            ZStack {
                                // ... some logic

                            }

                            , alignment: .leading)
                .gesture(
                    DragGesture(minimumDistance: 0, coordinateSpace: .global)
                        .onChanged { gesture in
                            print("Tap location: \(gesture.startLocation)")
                            
                        }
                )
                .allowsHitTesting(dragGestureMode == DragGestureEnum.TransformShape)
        }
    }
}

有谁知道在这种情况下启用手势组合((拖动或调整大小)或(点击或调整大小))的好方法(即应该在形状视图上检测到点击,应该在形状视图上检测到拖动或调整大小主视图和点击单个形状并在主视图上拖动是专有的)以获得预期的用户体验(防止调整大小手势被解释为点击或拖动)?

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    你可以同时使用手势修饰符,比如

        .simultaneousGesture(MagnificationGesture()
          ...
    

    【讨论】:

    • 如果getures在不同的视图中实现怎么办?上面的例子就是这种情况;点击手势在形状视图中实现,调整大小手势在图像视图中实现。一种选择是在形状视图中实现调整大小和拖动,并根据手势调整图像视图的大小或修改形状视图。
    • 它们是否在一个视图层次结构中并不重要
    猜你喜欢
    • 2020-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-18
    • 2020-10-19
    相关资源
    最近更新 更多