【问题标题】:How to create custom form button with non-clickable rectangle area in swift?如何在swift中创建具有不可点击矩形区域的自定义表单按钮?
【发布时间】:2017-05-06 16:41:03
【问题描述】:

这是我的 Button 类。

@IBDesignable
class Button: UIButton {
    var cornerRadii = CGSize()

    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            cornerRadii = CGSize(width: cornerRadius, height: cornerRadius)
        }
    }

    @IBInspectable var color: UIColor = .green

    override func draw(_ rect: CGRect) {
        super.draw(rect)

        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: cornerRadii)
        let shapeLayer = CAShapeLayer()
        shapeLayer.frame = self.layer.bounds
        shapeLayer.path = path.cgPath
        layer.mask = shapeLayer
        color.setFill()
        path.fill()
    }
}

所以一切都很顺利。我的按钮有一个半圆形,所以实际上当我点击按钮框架的空角时,我不希望它被按下,但它确实发生了。我认为面具可以帮助我解决这个问题,但我没能做到。

那么,我如何创建一个带有两个不可点击的空角的按钮?

【问题讨论】:

  • 尝试覆盖命中测试方法。在圈内时返回 nil,否则返回 super。

标签: ios swift button uibezierpath


【解决方案1】:

从 cmets 开始,您可以覆盖按钮上的命中测试方法。

如果您需要禁用路径外的触摸,这对我有用:

class Button: UIButton {
    var cornerRadii = CGSize()

    @IBInspectable var cornerRadius: CGFloat = 0 {
        didSet {
            cornerRadii = CGSize(width: cornerRadius, height: cornerRadius)
        }
    }

    @IBInspectable var color: UIColor = .green

    var currentPath: UIBezierPath?

    override func draw(_ rect: CGRect) {
        super.draw(rect)


        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: cornerRadii)
        currentPath = path // Save the path here to be used in hit test


        let shapeLayer = CAShapeLayer()
        shapeLayer.frame = self.layer.bounds
        shapeLayer.path = path.cgPath
        layer.mask = shapeLayer
        color.setFill()
        path.fill()
    }

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {

        // check if point is outside the given path and return nil in that case. Otherwise return super
        if currentPath?.contains(point) == false {
            return nil
        } else {
            return super.hitTest(point, with: event)
        }
    }
}

【讨论】:

    【解决方案2】:

    为您的自定义 Button 提供 point inside 方法:

    override public func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: cornerRadii)
        return path.contains(point)
    }
    

    【讨论】:

      【解决方案3】:

      您可以覆盖 whitest 方法并检查接触点是否在您的较笨路径内。您可以检查path.containsPoint(point); 以查找它是否在里面。如果它的内部返回 self 或 nil。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-02
        • 2020-07-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多