SwiftUI缺失UITouch属性:如何在纯SwiftUI中获取force与majorRadius?
在纯SwiftUI中获取触摸的force与majorRadius属性
SwiftUI原生手势(如DragGesture)仅提供触摸坐标、位移等基础信息,并未直接暴露UITouch的force(按压力度)和majorRadius(触摸触点半径)属性。目前纯SwiftUI环境下没有原生API能直接获取这两个值,必须通过与UIKit桥接的方式实现,以下是具体方案:
1. 封装UIKit触摸处理组件
通过UIViewRepresentable创建一个能捕获触摸事件的UIView包装器,在其中监听UITouch的属性变化,并将数据传递给SwiftUI:
import SwiftUI struct TouchCaptureView: UIViewRepresentable { // 回调函数,传递触摸数据 var onTouchUpdate: (CGFloat, CGFloat) -> Void func makeUIView(context: Context) -> UIView { let view = UIView() view.isUserInteractionEnabled = true // 添加点击手势识别器 view.addGestureRecognizer(UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap(_:)))) // 添加长按手势识别器,支持持续获取数据 view.addGestureRecognizer(UILongPressGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleLongPress(_:)))) return view } func updateUIView(_ uiView: UIView, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(onTouchUpdate: onTouchUpdate) } class Coordinator: NSObject { var onTouchUpdate: (CGFloat, CGFloat) -> Void init(onTouchUpdate: @escaping (CGFloat, CGFloat)) { self.onTouchUpdate = onTouchUpdate } @objc func handleTap(_ gesture: UITapGestureRecognizer) { guard let touch = gesture.touches.first else { return } onTouchUpdate(touch.force, touch.majorRadius) } @objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) { guard let touch = gesture.touches.first else { return } // 长按过程中持续更新数据 if gesture.state == .began || gesture.state == .changed { onTouchUpdate(touch.force, touch.majorRadius) } } } }
2. 在SwiftUI视图中使用该组件
将封装好的TouchCaptureView嵌入SwiftUI视图,接收并展示触摸数据:
struct ContentView: View { @State private var touchForce: CGFloat = 0 @State private var touchRadius: CGFloat = 0 var body: some View { VStack(spacing: 20) { Text("按压力度: \(touchForce, specifier: "%.2f")") Text("触点半径: \(touchRadius, specifier: "%.2f")") // 占据大部分区域的触摸捕获视图 TouchCaptureView { force, radius in touchForce = force touchRadius = radius } .background(Color.blue.opacity(0.2)) .cornerRadius(10) } .padding() } }
补充说明
- 上述方案虽依赖UIKit的
UITouchAPI,但属于SwiftUI与UIKit的标准桥接方式,是目前实现该需求的唯一可行路径。 - 若需要支持拖拽过程中的持续数据更新,可替换为
UIPanGestureRecognizer,在其changed状态下获取触摸数据。 force属性取值范围为0到设备支持的最大压力(可通过UITouch.maximumPossibleForce获取),majorRadius代表触摸触点的近似半径。
内容的提问来源于stack exchange,提问作者Ziv Adler
相关产品推荐
相关产品推荐

