使用 BezierUIView 创建三角形按钮

Creating Triangle Shaped Button with BezierUIView

我一直在尝试创建一个三角形按钮。为此,最初我尝试使用 BezierPath 创建一个基本的三角形。

为了创建一个三角形;我创建了一个 UIView Class。这是代码:

class BezierView: UIView {

override func draw(_ rect: CGRect) {
    
    let triangle = UIBezierPath()
    triangle.move(to: CGPoint(x: 200, y: 200))
    triangle.addLine(to: CGPoint(x: 160, y: 240))
    triangle.addLine(to: CGPoint(x: 250, y: 240))
    triangle.close()
    

}

在创建 Bezierview 的 class 之后,我尝试在我的主 ViewController.

中调用此自定义 class
 class ViewController: UIViewController {


  override func viewDidLoad() {

    super.viewDidLoad()
    
    let bezierView = BezierView(frame: CGRect(x: 100, y: 100, width: 10, height: 10)) // Here I'm trying to determine the location and size of the triangle
    
    bezierView.backgroundColor = .black
    
    self.view.addSubview(bezierView)

 }
}

这段代码所做的只是将一个黑色矩形 Shape 带到屏幕上。当我尝试绘制基本三角形时,我的代码块无法正常工作。

虽然在创建了那种三角形后,我想将它用作UIButton 的框架。那么这有可能吗?我可以将按钮的框架设置为那个定制的三角形吗?据我所知; frame 是一个 CGRect,不能转换为 UIBezierPath。我能为这两个问题做些什么。 (首先创建一个三角形,然后将按钮框架塑造成自定义的三角形形状)

感谢您的帮助。希望一切都解释清楚了。

干杯。

首先,您可以直接创建一个UIButton的子class并添加创建一个形状。 其次,使用按钮框架矩形创建三角形,因此三角形是动态的并且取决于按钮的大小和框架。

此外,使用 .fill() 将背景颜色设置为三角形。

这里是子按钮class。

class TriangleButtonView: UIButton {
    
    private let triangle = UIBezierPath()
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        triangle.move(to: CGPoint(x: 0, y: rect.height))
        triangle.addLine(to: CGPoint(x:rect.width/2, y: 0))
        triangle.addLine(to: CGPoint(x:rect.width, y:rect.height))
        triangle.close()
        UIColor.red.setFill() //<--- Fill your color here
        triangle.fill()
    }
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        // This is for allow touches only in shape area.
        if triangle.contains(touches.first?.location(in: self) ?? .zero) {
            super.touchesBegan(touches, with: event)
            // or you can use send action
            // self.sendActions(for: .touchUpInside)
        }
    }
}

你的视图控制器,

class ViewController: UIViewController {
      override func viewDidLoad() {
        super.viewDidLoad()
        let button = TriangleButtonView(frame: CGRect(x: 100, y: 100, width: 10, height: 10))
        self.view.addSubview(button)
    }
}

您的代码中的问题是,您设置的三角点多于视图控制器中的给定框架 class。

  1. 使用贝塞尔曲线路径为按钮绘制三角形图标是一种矫枉过正。 只需使用图像/图标/SFSymbol。 SFSymbol 有一个空心三角形,一个实心三角形,还有左右实心三角形。如果您不能或不想使用 SFSymbols,只需使用图像(从 iOS 14 开始甚至支持 SVG 图像)。

  2. 如果您不介意只显示一个三角形按钮,那么以上几点可以解决您的问题。如果你还想只允许在三角形区域内点击,而不是整个按钮的框架矩形(除非绝对必要,否则不推荐),使用图像视图而不是按钮和 handle the touches 你自己,而不是按钮的默认值动作。因为你正在处理一个三角形,复习一些基本的学校水平的几何应该有助于你找到你的三角形中的哪些接触:)。

编辑:

在下面回答您的评论的更多详细信息:

  • UIButtonUIView,它使用额外的子视图(标签和图像)、手势、状态和动作提供特定行为
  • 如果您不使用 UIButton,默认情况下您将无法使用其中任何一项
  • 但是,您所期望的(只允许点击一个特定区域)并不是 UIButton 提供的默认行为之一。事实上 none 的视图默认提供这种行为
  • 因此无论您使用按钮还是图像,您都必须编写实现
  • 您可以找到 similar solutions 作为实施参考
  • 但是对于 UIView / UIImage,你有一种干净的状态,只有你的实现有效。使用 UIButton,您需要确保按钮自身的触摸处理不会干扰您的触摸处理代码