[英]How to create an IBDesignable custom UIView from a UIBezierPath?
我想塑造一個UIView
並能夠在界面生成器中看到它的形狀,當我將以下類設置為我的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
}
}
幾個觀察:
您正在調用setFill
后跟fill
,但只有在繪制到圖形上下文中時才這樣做(例如,在draw(_:)
)。 使用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
子類的子類,則您不需要重新訪問所有這些覆蓋。
如果您有可設計的視圖,建議將其放在單獨的目標中。 這樣,故事板中視圖的渲染不依賴於主項目中可能正在進行的任何工作。 只要可設計目標(通常是帶有Kit
后綴的主要目標的名稱)可以構建,就可以渲染可設計視圖。
例如,這里是您的可設計視圖的再現,在單獨的框架目標中,並在故事板中使用,其中所討論的視圖具有藍色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
}
}
這完成了同樣的事情,但我認為填充顏色與背景顏色的區別更直觀。 但是您可能有其他原因使用遮罩方法,但只要確保如果您這樣做,在遮罩后您有一些東西要顯示(例如背景顏色或您正在渲染的其他東西)。
請添加“super.layoutSubviews()”
override func layoutSubviews() {
setupMask()
super.layoutSubviews()
}
通過這種方式,您的設計視圖將是“最新的”。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.