iOS 中曲线视图的点按问题
Tap issue with curve views in iOS
我需要创建一个合并了顶视图和底视图的视图,其中顶视图需要在底部有一条曲线,并且顶视图和底视图都在点击时执行不同的操作。我能够如下创建此视图
这是我的故事板约束的截图
这是我的曲线图class
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
中的实现
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)
}
}
输出:
我需要创建一个合并了顶视图和底视图的视图,其中顶视图需要在底部有一条曲线,并且顶视图和底视图都在点击时执行不同的操作。我能够如下创建此视图
这是我的故事板约束的截图
这是我的曲线图class
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
中的实现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)
}
}
输出: