程序员SwiftUI 工具集SwiftUI学习与实践

SwiftUI-手势

2020-07-12  本文已影响0人  否极泰来_L

SwiftUI为视图提供了许多手势,比如:
单击onTapGesture()
多击onTapGesture(count:)
长按onLongPressGesture()
放大MagnificationGesture()
旋转RotationGesture()

单击
Text("单击")
      .onTapGesture {
          print("单击🚀")
}
双击
Text("双击")
      .onTapGesture(count: 2) {
          print("双击🚀")
}
长按

长按相比单击手势复杂一点,是可以定制的。例如,指定需要满足的最少时长和最大时长。

Text("长按")
    .onLongPressGesture(minimumDuration: 1, maximumDistance: 3, pressing: { (isProgress) in
        print("长按进行中 -> \(isProgress)")
     }) {
         print("长按🚀")
}

长按进行中 -> true
长按进行中 -> false
长按🚀

对于更高级的手势,你需要使用gesture()Modifier,并提供DragGestureLongPressGestureMagnificationGestureRotationGestureTapGesture。这些手势都有特定Modifier,最常用包括手势进行中onEnded (),已完成onEnded (),你可以在这里执行动作。

放大
struct ContentView: View {
    @State private var currentAmount: CGFloat = 0
    @State private var finalAmount: CGFloat = 1

    var body: some View {
        Text("放大")
            .scaleEffect(finalAmount + currentAmount)
            .gesture(
                MagnificationGesture()
                    .onChanged { amount in
                        self.currentAmount = amount - 1
                    }
                    .onEnded { amount in
                        self.finalAmount += self.currentAmount 
                        self.currentAmount = 0
                    }
            )
    }
}
旋转
struct ContentView: View {
    @State private var currentAngle: Angle = .degrees(0)
    @State private var finalAngle: Angle = .degrees(0)

    var body: some View {
        Text("旋转")
            .rotationEffect(currentAmount + finalAmount)
            .gesture(
                RotationGesture()
                    .onChanged { angle in
                        self.currentAmount = angle
                    }
                    .onEnded { angle in
                        self.finalAmount += self.currentAmount
                        self.currentAmount = .degrees(0)
                    }
            )
    }
}
手势冲突

加入子视图和父视图同时有单击手势,点击子视图默认只会触发子视图的单击手势,我们可以使用highPriorityGesture ()来强制父视图的手势优先。或者使用simultaneousGesture ()来使父视图和子视图的手势同时触发。

struct ContentView: View {
    var body: some View {
        VStack {
            Text("单击")
                .onTapGesture {
                    print("单击🚀")
                }
        }
    // simultaneousGesture(父视图和子视图同时触发) highPriorityGesture(高优先级,优先触发)
        .simultaneousGesture(
            TapGesture()
                .onEnded { _ in
                    print("VStack🚀")
                }
        )
    }
}
手势序列

SwiftUI还可以创建手势序列,序列中的手势之间存在引用,只有前一个手势成功识别之后才会被激活识别。

struct DragView: View {
    
    // 圆被拖拽的偏移量
    @State private var offset = CGSize.zero
    // 圆是否正在被拖拽
    @State private var isDragging = false

    var body: some View {
        
        // 拖拽手势更新偏移量,结束后更新偏移量和isDragging
        let dragGesture = DragGesture()
            .onChanged { (value) in
                self.offset = value.translation
        }
        .onEnded { (_) in
            withAnimation {
                self.offset = .zero
                self.isDragging = false
            }
        }
        // 长按手势激活isDragging
        let pressGesture = LongPressGesture()
            .onEnded { (value) in
                withAnimation {
                    self.isDragging = true
                }
        }
        // 组合手势
        let combined = pressGesture.sequenced(before: dragGesture)
        
        return Circle()
            .fill(Color.blue)
            .frame(width: 80, height: 80)
            .scaleEffect(isDragging ? 2 : 1)
            .offset(offset)
            .gesture(combined)
    }
}

全部示例代码

ContentView
struct ContentView: View {
    
    // 记录放大的值
    @State private var currentAmount: CGFloat = 0
    @State private var finalAmount: CGFloat = 1
    // 记录旋转的值
    @State private var currentAngle: Angle = .degrees(0)
    @State private var finalAngle: Angle = .degrees(0)
    
    var body: some View {
        
        VStack {
        
            VStack {
                Text("单击")
                    .onTapGesture {
                        print("单击🚀")
                }.padding(.top).padding(.horizontal)
                Text("双击")
                    .onTapGesture(count: 2) {
                        print("双击🚀")
                }.padding(.top)
                Text("长按")
                    .onLongPressGesture(minimumDuration: 1, maximumDistance: 3, pressing: { (isProgress) in
                        print("长按进行中 -> \(isProgress)")
                    }) {
                        print("长按🚀")
                }.padding(.top)
                Text("放大")
                .scaleEffect(finalAmount + currentAmount)
                .gesture(
                    MagnificationGesture()
                        .onChanged({ (amount) in
                            self.currentAmount = amount - 1
                        })
                        .onEnded({ (amount) in
                            self.finalAmount += self.currentAmount
                            self.currentAmount = 0
                        })
                ).padding(.top)
                Text("旋转")
                .rotationEffect(finalAngle + currentAngle)
                .gesture(
                    RotationGesture()
                        .onChanged({ (angle) in
                            self.currentAngle = angle
                        })
                        .onEnded({ (angle) in
                            self.finalAngle += self.currentAngle
                            self.currentAngle = .degrees(0)
                        })
                ).padding(.vertical)
                
            }
            .font(.title)
            .background(Color.red)
    //          simultaneousGesture(父视图和子视图同时触发) highPriorityGesture(高优先级,优先触发)
            .simultaneousGesture(
                TapGesture()
                    .onEnded({ (_) in
                        print("VStack🚀")
                    })
            )
            
            // 拖拽view
            DragView()
        }
    }
}
DragView
struct DragView: View {
    
    // 手势序列
    // 圆被拖拽的偏移量
    @State private var offset = CGSize.zero
    // 圆是否正在被拖拽
    @State private var isDragging = false

    var body: some View {
        
        // 拖拽手势更新偏移量,结束后更新偏移量和isDragging
        let dragGesture = DragGesture()
            .onChanged { (value) in
                self.offset = value.translation
        }
        .onEnded { (_) in
            withAnimation {
                self.offset = .zero
                self.isDragging = false
            }
        }
        // 长按手势激活isDragging
        let pressGesture = LongPressGesture()
            .onEnded { (value) in
                withAnimation {
                    self.isDragging = true
                }
        }
        // 组合手势
        let combined = pressGesture.sequenced(before: dragGesture)
        
        return Circle()
            .fill(Color.blue)
            .frame(width: 80, height: 80)
            .scaleEffect(isDragging ? 2 : 1)
            .offset(offset)
            .gesture(combined)
    }
}
上一篇下一篇

猜你喜欢

热点阅读