我需要创建一个合并了顶视图和底视图的视图,其中顶视图的底部需要有一条曲线,而顶视图和底视图都需要在点击时执行不同的操作。我能够如下创建此视图
这是我的故事板约束的屏幕截图
这是我的曲线视图类
class CurveView: UIView {
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
self.createBottomCurve()
}
private func createBottomCurve() {
let offset: CGFloat = self.frame.width / 1.2
let bounds: CGRect = self.bounds
let rectBounds: CGRect = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width, height: bounds.size.height / 2)
let rectPath: UIBezierPath = UIBezierPath(rect: rectBounds)
let ovalBounds: CGRect = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width: bounds.size.width + offset, height: bounds.size.height)
let ovalPath: UIBezierPath = UIBezierPath(ovalIn: ovalBounds)
rectPath.append(ovalPath)
let maskLayer: CAShapeLayer = CAShapeLayer()
maskLayer.frame = bounds
maskLayer.path = rectPath.cgPath
self.layer.mask = maskLayer
}
}
这是viewcontroller类中的实现
class ViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var greenCurveView: CurveView!
@IBOutlet weak var yellowView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let greenViewTap = UITapGestureRecognizer(target: self, action: #selector(handleGreenViewTap(_:)))
greenViewTap.delegate = self
greenCurveView.addGestureRecognizer(greenViewTap)
let yellowViewTap = UITapGestureRecognizer(target: self, action: #selector(handleYellowTap(_:)))
yellowViewTap.delegate = self
yellowView.addGestureRecognizer(yellowViewTap)
}
@objc func handleGreenViewTap(_ pan: UITapGestureRecognizer ){
print("Green View is tapped")
}
@objc func handleYellowTap(_ pan: UITapGestureRecognizer ){
print("Yellow View is tapped")
}
}
这很好,除了在下图中红色点击突出显示的矩形区域中的黄色视图的情况下。在下图中,如果单击矩形中的黄色区域,则会获得绿色视图的水龙头,这是有意义的,因为黄色视图位于绿色视图之后。那么,如何确定该区域的黄色区域?任何帮助表示赞赏
您需要指示CurveView
可以在哪里窃听,在这种情况下,应在其自己的路径内:
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return rectPath.contains(point)
}
所以您的CurveView
总体上看起来像这样:
class CurveView: UIView {
var rectPath = UIBezierPath()
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
self.createBottomCurve()
}
private func createBottomCurve() {
let offset: CGFloat = self.frame.width / 1.2
let bounds: CGRect = self.bounds
let rectBounds: CGRect = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.size.width, height: bounds.size.height / 2)
rectPath = UIBezierPath(rect: rectBounds)
let ovalBounds: CGRect = CGRect(x: bounds.origin.x - offset / 2, y: bounds.origin.y, width: bounds.size.width + offset, height: bounds.size.height)
let ovalPath: UIBezierPath = UIBezierPath(ovalIn: ovalBounds)
rectPath.append(ovalPath)
let maskLayer: CAShapeLayer = CAShapeLayer()
maskLayer.frame = bounds
maskLayer.path = rectPath.cgPath
self.layer.mask = maskLayer
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
return rectPath.contains(point)
}
}
输出: