【问题标题】:Creating Triangle Shaped Button with BezierUIView使用 BezierUIView 创建三角形按钮
【发布时间】:2021-02-15 10:10:53
【问题描述】:

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

为了创建一个三角形;我创建了一个 UIView 类。代码如下:

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 类之后,我尝试在我的主 ViewController 中调用这个自定义类。

 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)

 }
}

这段代码所做的只是将一个黑色矩形形状带到屏幕上。当我尝试绘制一个基本三角形时,我的代码块不起作用。

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

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

干杯。

【问题讨论】:

    标签: ios swift uibezierpath


    【解决方案1】:

    首先,您可以直接创建 UIButton 的子类并添加创建形状。 其次,使用button frame rect来创建一个三角形,所以这个三角形是动态的,并且依赖于button的大小和边框。

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

    这里是按钮的子类。

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

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

    【讨论】:

    • 难以置信的解释。谢谢!现在我有一个小问题。画一个三角形就完成了。为了能够使用指定的三角形,我将 IBAction Button 的类更改为客户 "TriangleButtonView" 。但现在我需要编辑按钮的可点击部分。我的按钮内部形状为三角形,但可点击部分仍然是矩形。所以我也可以点击三角形外部。有没有办法编辑按钮的可点击部分?
    • 附加问题:为什么我们使用 super.draw(rect) 和 triangle.close() ?因为即使没有它们,代码也能完美运行。谢谢。
    • 不需要,但如果我们有多个此类的子类,超级方法很有用,而且这种情况下也不需要关闭路径。
    • 您最近更新的这段代码完美运行。试图了解它是如何工作的:) 非常感谢。
    【解决方案2】:
    1. 使用贝塞尔路径为按钮绘制三角形图标是一种矫枉过正。 只需使用图像/图标/SFSymbol。 SFSymbol 有一个空三角形、一个实心三角形以及左右实心三角形。如果您不能或不想使用 SFSymbols,只需使用图像(从 iOS 14 开始甚至支持 SVG 图像)。

    2. 如果您只需要显示一个三角形按钮就可以了,以上几点可以解决您的问题。如果您还希望只允许在三角形区域内点击,而不是整个按钮的框架矩形(除非绝对必要,否则不推荐),请使用图像视图而不是按钮和 handle the touches 自己,而不是按钮的默认操作。由于您正在使用三角形,因此复习一些基本的学校级别几何图形可以帮助您找到三角形内的哪些触摸:)。

    编辑:

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

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

    【讨论】:

    • 感谢您提出不同的观点。我可能会选择这种方式在应用程序中申请。这看起来容易一些。但正如你所说,我只想允许点击按钮的部分,因为三角形只是。那么我可以在不使用可点击的图像视图的情况下做到这一点吗?使用可点击图像而不是按钮有什么缺点?我想三角形的可点击图像可能会解决我的问题。
    • 为了回答您在上面的评论中提出的问题,写得有点长,所以直接将其添加到答案中:)
    猜你喜欢
    • 2013-05-31
    • 2017-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-30
    • 2016-04-06
    • 1970-01-01
    相关资源
    最近更新 更多