如何从 UIBezierPath 创建 IBDesignable 自定义 UIView?
Posted
技术标签:
【中文标题】如何从 UIBezierPath 创建 IBDesignable 自定义 UIView?【英文标题】:How to create an IBDesignable custom UIView from a UIBezierPath? 【发布时间】:2018-09-14 00:38:28 【问题描述】:我想塑造一个 UIView
并能够在 Interface Builder 中看到它的形状,当我将以下类设置为我的 UIView
时,它无法构建,我不确定错误在哪里。
@IBDesignable
class CircleExampleView: UIView
override func layoutSubviews()
setupMask()
func setupMask()
let path = makePath()
// mask the whole view to that shape
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
private func makePath() -> UIBezierPath
//// Oval Drawing
let ovalPath = UIBezierPath(ovalIn: CGRect(x: 11, y: 12, width: 30, height: 30))
UIColor.gray.setFill()
ovalPath.fill()
return ovalPath
【问题讨论】:
【参考方案1】:几个观察:
-
1234563使用
CAShapeLayer
时,应改为设置CAShapeLayer
的fillColor
。
您正在使用CAShapeLayer
设置视图的掩码。如果您的UIView
没有可识别的backgroundColor
,您将看不到任何内容。
如果您将视图的背景颜色设置为蓝色,如下所示,您的遮罩将在遮罩允许的任何位置(在路径的椭圆中)显示蓝色背景。
你已经实现了layoutSubviews
。通常,只有当您在此处执行取决于视图的bounds
的操作时,您才会这样做。例如,下面是椭圆路径基于视图的bounds
的再现:
@IBDesignable
class CircleView: UIView
override func layoutSubviews()
super.layoutSubviews()
setupMask()
private func setupMask()
let mask = CAShapeLayer()
mask.path = path.cgPath
mask.fillColor = UIColor.gray.cgColor
layer.mask = mask
private var path: UIBezierPath
return UIBezierPath(ovalIn: bounds)
正如 E. Coms 所说,如果你覆盖 layoutSubviews
,你真的应该调用 super
实现。这并不重要,因为默认实现实际上什么都不做,但这是最佳实践。例如。如果您稍后将该类更改为其他 UIView
子类的子类,您就不必重新访问所有这些覆盖。
如果您有可设计的视图,建议将其放在单独的目标中。这样,故事板中视图的渲染不依赖于主项目中可能正在进行的任何工作。只要 designables 目标(通常是您的主要目标的名称,带有Kit
后缀)可以构建,就可以渲染 designable 视图。
例如,这里是您的可设计视图的再现,在一个单独的框架目标中,并在故事板中使用,其中相关视图具有蓝色 backgroundColor
:
对于它的价值,我认为必须遮盖以显示椭圆形内的背景颜色非常令人困惑。应用开发者必须设置“背景”颜色才能设置椭圆内的内容,而不是背景。
我可能会删除“掩码”逻辑,而是为可设计视图提供一个可检查的属性 fillColor
,然后使用 fillColor
添加一个 CAShapeLayer
作为子层:
@IBDesignable
class CircleView: UIView
private var shapeLayer = CAShapeLayer()
@IBInspectable var fillColor: UIColor = .blue
didSet
shapeLayer.fillColor = fillColor.cgColor
override init(frame: CGRect = .zero)
super.init(frame: frame)
configure()
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
configure()
private func configure()
shapeLayer.fillColor = fillColor.cgColor
layer.addSublayer(shapeLayer)
override func layoutSubviews()
super.layoutSubviews()
shapeLayer.path = UIBezierPath(ovalIn: bounds).cgPath
这完成了同样的事情,但我认为填充颜色与背景颜色的区别更直观。但是你可能有其他原因使用遮罩方法,但只要确保你这样做,在它被遮罩后你有一些东西要显示(例如背景颜色或你正在渲染的其他东西)。
【讨论】:
【参考方案2】:请添加“super.layoutSubviews()”
override func layoutSubviews()
setupMask()
super.layoutSubviews()
通过这种方式,您的设计视图将是“最新的”。
【讨论】:
以上是关于如何从 UIBezierPath 创建 IBDesignable 自定义 UIView?的主要内容,如果未能解决你的问题,请参考以下文章