簡體   English   中英

如何從 UIBezierPath 創建一個 IBDesignable 自定義 UIView?

[英]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
    }
}

幾個觀察:

  1. 您正在調用setFill后跟fill ,但只有在繪制到圖形上下文中時才這樣做(例如,在draw(_:) )。 使用CAShapeLayer ,您應該設置CAShapeLayerfillColor

  2. 您正在使用CAShapeLayer來設置視圖的遮罩。 如果您的UIView沒有可辨別的backgroundColor ,您將看不到任何內容。

    如果您將視圖的背景顏色設置為藍色,如下所示,您的蒙版將在蒙版允許的任何地方(在路徑的橢圓中)顯示藍色背景。

  3. 您已經實現了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) } }
  4. 正如 E. Coms 所說,如果你覆蓋layoutSubviews ,你真的應該調用super實現。 這並不重要,因為默認實現實際上什么都不做,但這是最佳實踐。 例如,如果您稍后將此類更改為其他UIView子類的子類,則您不需要重新訪問所有這些覆蓋。

  5. 如果您有可設計的視圖,建議將其放在單獨的目標中。 這樣,故事板中視圖的渲染不依賴於主項目中可能正在進行的任何工作。 只要可設計目標(通常是帶有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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM