Swift中在View上触发3D-Touch并显示触控位置矩形的实现问询
当然可以!作为iOS新手,你搜资料时大概率会先看到Peek & Pop或者主屏幕快捷操作这些系统级的3D-Touch用法,但其实完全可以在自定义View上实现你要的压力触控效果——触发时在触摸位置显示矩形,还能给这个矩形加后续手势操作。我来给你详细讲清楚怎么做:
核心原理:利用
UITouch的Force属性 iOS的UITouch类提供了两个关键属性来处理压力触控:
force: 当前触摸的压力值(范围0到maximumPossibleForce)maximumPossibleForce: 当前设备能检测到的最大压力值(不同设备可能有差异)
我们只需要在自定义View中重写触摸事件方法,判断触摸压力是否达到设定阈值,就能触发显示矩形的逻辑,再给矩形添加手势识别器处理后续操作即可。
实现步骤&代码示例
下面是一个完整的自定义View实现,包含压力触发显示矩形、拖动矩形、点击矩形等功能:
import UIKit class ForceTouchCustomView: UIView { // 用于显示的矩形View private var touchRectView: UIView? override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesBegan(touches, with: event) guard let touch = touches.first, traitCollection.forceTouchCapability == .available else { // 设备不支持Force Touch时直接返回 return } // 设置触发阈值(比如取最大压力的20%,可根据需求调整) let triggerThreshold = touch.maximumPossibleForce * 0.2 if touch.force >= triggerThreshold { showTouchRect(at: touch.location(in: self)) } } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesMoved(touches, with: event) guard let touch = touches.first, traitCollection.forceTouchCapability == .available else { return } let triggerThreshold = touch.maximumPossibleForce * 0.2 if touch.force >= triggerThreshold { // 压力足够时,更新矩形位置到当前触摸点 touchRectView?.center = touch.location(in: self) } else { // 压力不足时隐藏矩形 hideTouchRect() } } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesEnded(touches, with: event) hideTouchRect() } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesCancelled(touches, with: event) hideTouchRect() } // 显示触摸位置的矩形 private func showTouchRect(at point: CGPoint) { if touchRectView == nil { let rectView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) rectView.backgroundColor = UIColor.blue.withAlphaComponent(0.3) rectView.layer.cornerRadius = 8 rectView.isUserInteractionEnabled = true // 添加Pan手势:让矩形可以被拖动 let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handlePan(_:))) rectView.addGestureRecognizer(panGesture) // 添加Tap手势:点击矩形执行自定义操作 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:))) rectView.addGestureRecognizer(tapGesture) touchRectView = rectView addSubview(rectView) } touchRectView?.center = point touchRectView?.alpha = 1.0 } // 隐藏/移除矩形 private func hideTouchRect() { UIView.animate(withDuration: 0.2) { self.touchRectView?.alpha = 0.0 } completion: { _ in self.touchRectView?.removeFromSuperview() self.touchRectView = nil } } // 处理矩形拖动逻辑 @objc private func handlePan(_ gesture: UIPanGestureRecognizer) { guard let rectView = gesture.view else { return } let translation = gesture.translation(in: self) rectView.center = CGPoint(x: rectView.center.x + translation.x, y: rectView.center.y + translation.y) gesture.setTranslation(.zero, in: self) } // 处理矩形点击逻辑 @objc private func handleTap(_ gesture: UITapGestureRecognizer) { print("矩形被点击啦!这里可以添加你的自定义操作") // 示例:点击后改变矩形颜色 gesture.view?.backgroundColor = UIColor.red.withAlphaComponent(0.3) } // 监听设备Force Touch支持状态变化 override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) if traitCollection.forceTouchCapability != .available { hideTouchRect() // 可选:提示用户当前设备不支持Force Touch } } }
额外注意事项
- 阈值调整:建议用
maximumPossibleForce的比例来设置阈值(比如20%),避免不同设备压力值差异导致的触发不一致 - 交互开关:确保自定义View的
isUserInteractionEnabled属性为true(默认是true,但如果手动设置过false要改回来) - 手势优先级:如果矩形上的手势和父View的触摸事件有冲突,可以通过
gestureRecognizer.require(toFail:)或者调整cancelsTouchesInView属性来解决 - 精细响应:如果需要根据压力大小动态改变矩形的大小/透明度,可以在
touchesMoved中实时获取touch.force值并更新UI
内容的提问来源于stack exchange,提问作者1zz0
相关产品推荐
相关产品推荐

