You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:31:26