代码之家  ›  专栏  ›  技术社区  ›  Jonathan Solorzano

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

  •  2
  • Jonathan Solorzano  · 技术社区  · 6 年前

    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
        }
    }
    
    2 回复  |  直到 6 年前
        1
  •  3
  •   Rob Md Fahim Faez Abir    6 年前

    1. setFill 然后 fill draw(_:) ). 使用时 CAShapeLayer ,则应设置 fillColor .

    2. CAShapeLayer公司 设置视图的遮罩。如果你的 UIView 没有可辨别的 backgroundColor ,你什么也看不到。

      如果将视图的背景色设置为蓝色,如下图所示,则遮罩将在遮罩允许的任何位置(在路径的椭圆形中)显示蓝色背景。

    3. 你已经实现了 layoutSubviews . 一般来说,只有当你在这里做的事情取决于 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说的,如果你 布局子视图 ,你真的应该打电话给 super 实施。这并不重要,因为默认实现实际上什么都不做,但这是最佳实践。例如,如果您后来将这个类更改为其他类的子类 UIView视图 子类,您不必重新访问所有这些重写。

    5. 如果你有一个可设计的视图,建议把它放在一个单独的目标中。这样,脚本中视图的呈现就不依赖于主项目中正在进行的任何工作。只要目标是可指定的(通常是你的主要目标的名称) Kit 后缀)可以构建,可以呈现可设计视图。

    例如,这里是您的可设计视图的一个格式副本,在一个单独的框架目标中,并在一个故事板中使用,其中所讨论的视图具有蓝色 背景色

    enter image description here


    值得一提的是,我认为必须用遮罩来显示椭圆形内部的背景色是非常令人困惑的。应用程序开发人员必须设置“背景”颜色才能设置椭圆形内部的内容,但不能设置背景。

    我可以去掉“掩码”逻辑,给可设计视图一个可检查的属性, 填充颜色 ,只需添加 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
  •  0
  •   E.Coms    6 年前

    请添加“超级布局子视图()"

    override func layoutSubviews() {
        setupMask()
        super.layoutSubviews()
    }
    

    这样,您的设计视图将是“最新的”。

    推荐文章