如何限制用户在绘制的贝塞尔路径外的触摸事件?
如何限制用户在绘制的贝塞尔路径外的触摸事件?
嗨,我来帮你搞定这个问题!你现在是想让触摸事件只在你用贝塞尔路径画的三角形区域内生效,对吧?其实核心思路就是让视图只识别路径内部的触摸点,咱们一步步来实现:
步骤1:把贝塞尔路径存为视图属性
首先,你不能只在绘制方法里临时创建路径,得把它存起来,这样后面判断触摸点的时候才能用到。咱们可以自定义一个UIView子类,添加一个属性来保存路径:
class TriangleView: UIView { // 用来保存绘制好的三角形路径 private var trianglePath: UIBezierPath? // 可以把圆角半径做成可配置的,方便在XIB里调整 @IBInspectable var cornerRadius: CGFloat = 0
步骤2:绘制路径并保存
接下来把你的三角形绘制逻辑放到视图的draw(_:)方法里,同时把创建好的路径赋值给咱们刚才定义的属性。我帮你补全了你没写完的路径代码(假设是右上角的直角三角形,你可以根据自己的需求调整坐标点):
override func draw(_ rect: CGRect) { super.draw(rect) let path = UIBezierPath() // 定义三角形的三个顶点,根据你的视图布局调整 let top = CGPoint(x: bounds.maxX, y: bounds.minY) let bottomRight = CGPoint(x: bounds.maxX, y: bounds.maxY) let bottomLeft = CGPoint(x: bounds.minX, y: bounds.maxY) // 绘制路径 path.move(to: top) path.addLine(to: bottomRight) path.addLine(to: bottomLeft) path.close() // 添加圆角(如果需要的话) if cornerRadius > 0 { // 给右下角添加圆角,其他角按需添加 path.addArc(withCenter: bottomRight, radius: cornerRadius, startAngle: .pi / 2, endAngle: .pi, clockwise: true) } // 保存路径,供触摸判断使用 trianglePath = path // 这里可以添加填充、边框的样式设置 UIColor.blue.setFill() path.fill() UIColor.black.setStroke() path.stroke() }
步骤3:重写触摸点判断方法
UIView有个自带的方法point(inside:with:),系统会用它来判断这个视图要不要响应触摸事件。咱们重写这个方法,让它只在触摸点位于路径内部时返回true:
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { // 如果路径还没创建,就用默认的判断逻辑 guard let path = trianglePath else { return super.point(inside: point, with: event) } // 判断触摸点是否在路径内部 return path.contains(point) }
步骤4:适配视图大小变化
如果你的视图大小可能会改变(比如屏幕旋转、布局调整),记得在layoutSubviews里触发重绘,保证路径是最新的:
override func layoutSubviews() { super.layoutSubviews() setNeedsDisplay() } }
最后一步:关联XIB视图
打开你的XIB文件,把那个半高的视图的类设置为咱们自定义的TriangleView,这样它就能自动应用上面的逻辑啦!
这样设置之后,只有当用户触摸到三角形路径内部时,视图才会响应触摸事件,路径外的区域就会忽略触摸啦~
备注:内容来源于stack exchange,提问作者Jitendra Modi




