我需要一个带边框的 View ,并且只有边框应该是可点击的。
这是我创建自定义 View 的代码,但是当我添加手势时,所有 View 都变得可点击。
class RectangleView: UIView {
override func draw(_ rect: CGRect) {
let aPath = UIBezierPath()
aPath.move(to: CGPoint(x:0, y: 0))
aPath.addLine(to: CGPoint(x:rect.width, y: 0))
aPath.addLine(to: CGPoint(x:rect.width, y:rect.height))
aPath.addLine(to: CGPoint(x:0, y:rect.height))
aPath.close()
UIColor.green.setStroke()
aPath.stroke()
UIColor.clear.setFill()
aPath.fill()
}
}
所以我会点击顶 View 下面的 View ,这个会在前面并且可以点击,所以我不能添加更小的 subview
最佳答案
这里最正确的方法是为 UIView
子类覆盖 func point(inside point: CGPoint, with event: UIEvent?) -> Bool
。
例子:
class CustomView: UIView {
private let shapeLayer = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
setupShapeLayer()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupShapeLayer() {
//Draw your own shape here
shapeLayer.frame = CGRect(x: 0, y: 0, width: frame.width, height: frame.height)
let innerPath = UIBezierPath(arcCenter: center, radius: frame.width / 3, startAngle: CGFloat(0), endAngle: CGFloat.pi * 2, clockwise: true)
let outerPath = UIBezierPath(arcCenter: center, radius: frame.width / 4, startAngle: CGFloat(0), endAngle: CGFloat.pi * 2, clockwise: true)
//Subtract inner path
innerPath.append(outerPath.reversing())
shapeLayer.path = innerPath.cgPath
shapeLayer.lineWidth = 10
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.fillColor = UIColor.yellow.cgColor
layer.addSublayer(shapeLayer)
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return shapeLayer.path?.contains(point) ?? false
}
}
现在您可以添加 UITapGestureRecognizer
来检查它是如何工作的:
class ViewController: UIViewController {
@IBOutlet weak var resultLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let customView = CustomView.init(frame: view.frame)
view.addSubview(customView)
let recognizer = UITapGestureRecognizer(target: self, action: #selector(tapAction))
view.addGestureRecognizer(recognizer)
}
@objc func tapAction(_ sender: UITapGestureRecognizer) {
let location = sender.location(in: sender.view)
let subview = view?.hitTest(location, with: nil)
if subview is CustomView {
resultLabel.text = "CustomView"
}
else {
resultLabel.text = "Other"
}
}
}
tapAction
的结果:
如果您需要多个 View ,有两种可能的选择:
- 将
CAShapeLayer
存储在一个CustomView
中,并在point
函数中对其进行迭代 - 为每个实例添加
CustomView
并在UITapGestureRecognizer
tap action 中迭代它
关于ios - 空 View ,只有可点击的边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47261289/