eli*_*ade 16 gesture swift swiftui
我试图检测手指何时第一次接触 SwiftUI 中的视图。我可以用 UIKit Events 很容易地做到这一点,但在 SwiftUI 中无法解决这个问题。
我已经尝试了最小移动为 0 的 DragGesture,但在您的手指移动之前它仍然不会改变。
TapGesture 仅在您抬起手指时才起作用,并且无论我将参数设置为什么,LongPressGesture 都不会足够快地触发。
DragGesture(minimumDistance: 0, coordinateSpace: .local).onChanged({ _ in print("down")})
LongPressGesture(minimumDuration: 0.01, maximumDistance: 100).onEnded({_ in print("down")})
Run Code Online (Sandbox Code Playgroud)
我想在手指与视图接触后立即检测 touchDown 事件。Apple 的默认手势对距离或时间都有限制。
更新:这不再是问题,因为 Apple 似乎更新了 DragGesture 的工作方式,或者我可能遇到了特定的上下文错误。
nil*_*ils 23
您可以.updating像这样使用修饰符:
struct TapTestView: View {
@GestureState private var isTapped = false
var body: some View {
let tap = DragGesture(minimumDistance: 0)
.updating($isTapped) { (_, isTapped, _) in
isTapped = true
}
return Text("Tap me!")
.foregroundColor(isTapped ? .red: .black)
.gesture(tap)
}
}
Run Code Online (Sandbox Code Playgroud)
一些注意事项:
@GestureState属性包装自动将其值重置为初始值时的姿态结束。这样您只需担心设置isTapped为true. false当交互结束时,它会自动再次出现。updating修改有三个参数这种怪异的关闭。在这种情况下,我们只对中间的感兴趣。它是inout的包装值的参数GestureState,因此我们可以在此处设置它。第一个参数是手势的当前值;第三个是Transaction包含一些动画上下文。sup*_*cio 13
您可以通过以下方式创建视图修改器:
extension View {
func onTouchDownGesture(callback: @escaping () -> Void) -> some View {
modifier(OnTouchDownGestureModifier(callback: callback))
}
}
private struct OnTouchDownGestureModifier: ViewModifier {
@State private var tapped = false
let callback: () -> Void
func body(content: Content) -> some View {
content
.simultaneousGesture(DragGesture(minimumDistance: 0)
.onChanged { _ in
if !self.tapped {
self.tapped = true
self.callback()
}
}
.onEnded { _ in
self.tapped = false
})
}
}
Run Code Online (Sandbox Code Playgroud)
现在你可以像这样使用它:
struct MyView: View {
var body: some View {
Text("Hello World")
.onTouchDownGesture {
print("View did tap!")
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果将这两个问题的代码结合起来:
UITapGestureRecognizer - 让它在触地时工作,而不是触地?
你可以做这样的事情:
ZStack {
Text("Test")
TapView {
print("Tapped")
}
}
Run Code Online (Sandbox Code Playgroud)
struct TapView: UIViewRepresentable {
var tappedCallback: (() -> Void)
func makeUIView(context: UIViewRepresentableContext<TapView>) -> TapView.UIViewType {
let v = UIView(frame: .zero)
let gesture = SingleTouchDownGestureRecognizer(target: context.coordinator,
action: #selector(Coordinator.tapped))
v.addGestureRecognizer(gesture)
return v
}
class Coordinator: NSObject {
var tappedCallback: (() -> Void)
init(tappedCallback: @escaping (() -> Void)) {
self.tappedCallback = tappedCallback
}
@objc func tapped(gesture:UITapGestureRecognizer) {
self.tappedCallback()
}
}
func makeCoordinator() -> TapView.Coordinator {
return Coordinator(tappedCallback:self.tappedCallback)
}
func updateUIView(_ uiView: UIView,
context: UIViewRepresentableContext<TapView>) {
}
}
class SingleTouchDownGestureRecognizer: UIGestureRecognizer {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
if self.state == .possible {
self.state = .recognized
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
self.state = .failed
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
self.state = .failed
}
}
Run Code Online (Sandbox Code Playgroud)
我们肯定可以做一些抽象,以便使用更像其他 SwiftUI 手势,但这是一个开始。希望苹果在某个时候支持这一点。
这是一个检测状态之间变化以及触摸坐标(在Text View本例中)的解决方案:
我添加了一个枚举来管理状态(对于那些UIKit怀旧使用开始、移动和结束)
导入 SwiftUI
struct ContentView: View {
@State var touchPoint = CGPoint(x: 0, y: 0)
@State var touchState = TouchState.none
var body: some View {
Text("\(touchState.name): \(Int(self.touchPoint.x)), \(Int(self.touchPoint.y))")
.border(Color.red).font(.largeTitle)
.gesture(
DragGesture(minimumDistance: 0)
.onChanged({ (touch) in
self.touchState = (self.touchState == .none || self.touchState == .ended) ? .began : .moved
self.touchPoint = touch.location
})
.onEnded({ (touch) in
self.touchPoint = touch.location
self.touchState = .ended
})
)
}
}
enum TouchState {
case none, began, moved, ended
var name: String {
return "\(self)"
}
}
Run Code Online (Sandbox Code Playgroud)
实际上,@eli_slade,您只需要这样:
LongPressGesture().onChanged {_ in print("down") }
Run Code Online (Sandbox Code Playgroud)
这是一个演示应用程序:
这是它的代码:
struct ContentView: View {
@State var isRed = false
var body: some View {
Circle()
.fill(isRed ? Color.red : Color.black)
.frame(width: 150, height: 150)
.gesture(LongPressGesture().onChanged { _ in self.isRed.toggle()})
}
}
Run Code Online (Sandbox Code Playgroud)
上述方法都不能完美地工作,就像DragGesture使表格无法滚动一样
经过长时间的寻找,我找到了这个圣杯!
注意:它是公开可用的,但 _ 前缀意味着它可能不适合生产
但效果仍然很好
._onButtonGesture(pressing: { pressing in
}, perform: {
})
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8257 次 |
| 最近记录: |