gpt4 book ai didi

ios - 如何从 UIBezierPath 创建 IBDesignable 自定义 UIView?

转载 作者:可可西里 更新时间:2023-11-01 01:08:26 25 4
gpt4 key购买 nike

我想塑造一个 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. 您正在调用 setFill,然后调用 fill,但您只有在绘制到图形上下文中时才这样做(例如,在 draw(_:) 中)。使用 CAShapeLayer 时,您应该改为设置 fillColor CAShapeLayer

  2. 您正在使用 CAShapeLayer 设置 View 的 mask 。如果您的 UIView 没有可识别的 backgroundColor,您将看不到任何东西。

    如果您将 View 的背景颜色设置为蓝色,如下所示,您的蒙版将在蒙版允许的任何位置(在您的路径的椭圆形中)显示蓝色背景。

  3. 您已经实现了layoutSubviews。通常,只有当您在此处执行的操作取决于 View 的 bounds 时,您才会这样做。例如,这是一个椭圆形路径基于 View 的 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. 如果您有可设计的 View ,建议将其放在单独的目标中。这样, Storyboard中 View 的呈现不依赖于主项目中可能正在进行的任何工作。只要可设计的目标(通常是你的主要目标的名称带有Kit后缀)可以构建,就可以渲染可设计的 View 。

例如,这是您的可设计 View 的再现,在单独的框架目标中,并在 Storyboard中使用,其中相关 View 具有蓝色 backgroundColor:

enter image description here


就其值(value)而言,我认为必须 mask 以显示椭圆内的背景颜色是非常令人困惑的。应用开发者必须设置“背景”颜色才能设置椭圆内的内容,但不能设置背景。

我可能会移除“掩码”逻辑,而是给可设计 View 一个可检查的属性,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
}
}

这完成了同样的事情,但我认为填充颜色与背景颜色的区别更直观。但是您可能有其他原因使用 mask 方法,但只要确保如果您这样做, mask 后您有一些东西可以显示(例如背景颜色或您正在渲染的其他东西)。

关于ios - 如何从 UIBezierPath 创建 IBDesignable 自定义 UIView?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52323491/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com