Нажмите вопрос с кривыми видами в iOS - PullRequest
1 голос
/ 09 марта 2020

У меня есть требование создать вид, который объединит вид сверху и снизу, где вид сверху должен иметь кривую внизу, а вид сверху и снизу выполняет различные действия при нажатии. Мне удалось создать этот вид, как показано ниже

enter image description here

Это скриншот моих ограничений раскадровки

enter image description here

Это мой класс представления кривой

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")
    }

}

Это прекрасно работает, за исключением сценария, в котором мы нажмите желтый вид в выделенной области прямоугольника красным на изображении ниже. На изображении ниже, если я нажму на желтую область в прямоугольнике, то получим прикосновение к зеленому виду, что имеет смысл, поскольку желтый вид находится за зеленым. Итак, как мне определить желтую область в этой области? Любая помощь приветствуется

enter image description here

1 Ответ

2 голосов
/ 09 марта 2020

Вам нужно указать 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)
    }
}

Выход:

image

...