在 Swift 中制作按钮的框架为三角形而不是矩形
Making the frame of a button triangle instead of rectangle in Swift
我有一个按钮,里面有一个三角形的图像。如下所示。
这个按钮还有一个三角形的可点击区域。为此,我创建了一个 UIButton class,如下所示。
按钮的可点击区域是三角形,但按钮的边框仍然是矩形。如何使按钮的框架成为三角形?如果有这种方法,我就不会用bezierpath来绘制可点击区域了,因为frame已经是三角形了。
谢谢。
class triangleShapeButton: UIButton {
private let triangle = UIBezierPath()
override func draw(_ rect: CGRect) {
super.draw(rect)
triangle.move(to: CGPoint(x: rect.width, y: rect.height))
triangle.addLine(to: CGPoint(x:rect.width/2, y: 0))
triangle.addLine(to: CGPoint(x: 0, y:rect.height))
triangle.close()
}
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)
}
}
编辑:我想要创建的是一个圆形按钮设置如下。在这样做的同时,一些三角形按钮的矩形框与下一个三角形按钮重叠。这会导致某些三角形按钮的可点击区域被挡住。我试图更改图层层次结构,但至少有一个按钮仍然与另一个按钮重叠。如果我无法更改框架,如何解决该问题?
非常感谢
我在你现有的代码中添加了一些代码,你可以试试。它可能对你有帮助。
我建议你要求矩形图像。
class TriangleShapeButton: UIButton {
let triangle = UIBezierPath()
let triangleLayer = CAShapeLayer()
override func draw(_ rect: CGRect) {
super.draw(rect)
triangle.move(to: CGPoint(x: rect.width, y: rect.height))
triangle.addLine(to: CGPoint(x:rect.width/2, y: 0))
triangle.addLine(to: CGPoint(x: 0, y:rect.height))
triangleLayer.path = triangle.cgPath
triangleLayer.fillColor = UIColor.red.cgColor
self.layer.addSublayer(triangleLayer)
triangle.close()
}
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)
}
}
}
您改变 UIView 形状的原始方法是不可能的。每个 UIView 都是低级别的矩形,因此在您的情况下相邻的三角形必然重叠。
但是还有一个不同的方法:
您可以为整个圆形视图创建一个 class。在这个 class 中,您修改 drawRect
函数,使各个三角形(或圆弧段)彼此相邻绘制。
在此 class 中,您可以覆盖 touchesBegan
方法。在那里您可以使用 touches.first?.location(in: self)
检查触摸位置。这会给你一个CGPoint
。然后你可以手动检查触摸发生在哪个三角形并相应地执行操作。
以下是我的建议:
使用 CAShapeLayers 绘制形状。如果您最终想用图像填充这些形状,请查看设置图层,其中图层的内容是 CGImage。添加另一个 CAShapeLayer 来绘制形状的边框。然后应用 CAShapeLayer 作为蒙版将图像裁剪为 triangle/circle 楔形。
现在,为了弄清楚用户点击了什么:
构建形状路径及其框架矩形的数组。当您在视图中点击时,首先循环遍历矩形数组并找到包含点击点的所有矩形。 (可能不止一个。)
然后遍历矩形中包含抽头的较小数组,并使用 UIBezierPath.contains(point:)
或 CGPath.contains(_:using:transform:)
找出哪些形状实际包含抽头点。
通过首先过滤您的数组以仅显示其帧包含抽头点的那些形状,您可以使用非常快速的测试来减少必须使用慢得多的路径 contains() 方法检查的形状数量。
我有一个按钮,里面有一个三角形的图像。如下所示。
这个按钮还有一个三角形的可点击区域。为此,我创建了一个 UIButton class,如下所示。
按钮的可点击区域是三角形,但按钮的边框仍然是矩形。如何使按钮的框架成为三角形?如果有这种方法,我就不会用bezierpath来绘制可点击区域了,因为frame已经是三角形了。
谢谢。
class triangleShapeButton: UIButton {
private let triangle = UIBezierPath()
override func draw(_ rect: CGRect) {
super.draw(rect)
triangle.move(to: CGPoint(x: rect.width, y: rect.height))
triangle.addLine(to: CGPoint(x:rect.width/2, y: 0))
triangle.addLine(to: CGPoint(x: 0, y:rect.height))
triangle.close()
}
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)
}
}
编辑:我想要创建的是一个圆形按钮设置如下。在这样做的同时,一些三角形按钮的矩形框与下一个三角形按钮重叠。这会导致某些三角形按钮的可点击区域被挡住。我试图更改图层层次结构,但至少有一个按钮仍然与另一个按钮重叠。如果我无法更改框架,如何解决该问题?
非常感谢
我在你现有的代码中添加了一些代码,你可以试试。它可能对你有帮助。 我建议你要求矩形图像。
class TriangleShapeButton: UIButton {
let triangle = UIBezierPath()
let triangleLayer = CAShapeLayer()
override func draw(_ rect: CGRect) {
super.draw(rect)
triangle.move(to: CGPoint(x: rect.width, y: rect.height))
triangle.addLine(to: CGPoint(x:rect.width/2, y: 0))
triangle.addLine(to: CGPoint(x: 0, y:rect.height))
triangleLayer.path = triangle.cgPath
triangleLayer.fillColor = UIColor.red.cgColor
self.layer.addSublayer(triangleLayer)
triangle.close()
}
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)
}
}
}
您改变 UIView 形状的原始方法是不可能的。每个 UIView 都是低级别的矩形,因此在您的情况下相邻的三角形必然重叠。
但是还有一个不同的方法:
您可以为整个圆形视图创建一个 class。在这个 class 中,您修改 drawRect
函数,使各个三角形(或圆弧段)彼此相邻绘制。
在此 class 中,您可以覆盖 touchesBegan
方法。在那里您可以使用 touches.first?.location(in: self)
检查触摸位置。这会给你一个CGPoint
。然后你可以手动检查触摸发生在哪个三角形并相应地执行操作。
以下是我的建议:
使用 CAShapeLayers 绘制形状。如果您最终想用图像填充这些形状,请查看设置图层,其中图层的内容是 CGImage。添加另一个 CAShapeLayer 来绘制形状的边框。然后应用 CAShapeLayer 作为蒙版将图像裁剪为 triangle/circle 楔形。
现在,为了弄清楚用户点击了什么: 构建形状路径及其框架矩形的数组。当您在视图中点击时,首先循环遍历矩形数组并找到包含点击点的所有矩形。 (可能不止一个。)
然后遍历矩形中包含抽头的较小数组,并使用 UIBezierPath.contains(point:)
或 CGPath.contains(_:using:transform:)
找出哪些形状实际包含抽头点。
通过首先过滤您的数组以仅显示其帧包含抽头点的那些形状,您可以使用非常快速的测试来减少必须使用慢得多的路径 contains() 方法检查的形状数量。