【问题标题】:How to add a custom shape to an UIImageView in Swift?如何在 Swift 中向 UIImageView 添加自定义形状?
【发布时间】:2020-01-11 11:18:00
【问题描述】:

我正在尝试将自定义形状添加到 imageView。请检查以下图片。

这是必填项:

这是我到目前为止所做的:

我是 Core Graphics 的新手,到目前为止我已经这样做了:

    private func customImageClipper(imageV: UIImageView){

    let path = UIBezierPath()

    let size = imageV.frame.size

    print(size)

    path.move(to: CGPoint(x: 0.0, y: size.height))

    path.addLine(to: CGPoint(x: 0.8, y: size.height/2))

    path.close()

    let shape = CAShapeLayer()

    shape.path = path.cgPath

    imageV.layer.sublayers = [shape]

}

我正在创建一个函数来实现这样的形状,但是每当我将imageView 传递给这个函数时,我根本看不到任何变化。我知道我必须从一个点移动到另一个点才能达到这个形状,但我从来没有这样做过。任何帮助,将不胜感激。这就是我调用这个函数的方式:

imageV.layoutIfNeeded()

customImageClipper(imageV: imageV)

P.S.:我没有使用 Storyboard,我是通过编程方式创建的。

【问题讨论】:

    标签: ios swift core-graphics uibezierpath cashapelayer


    【解决方案1】:

    有很多方法可以使用 UIBezierPaths 创建形状。 This 此处的帖子讨论了使用 draw 函数创建形状。

    这是在单元格中使用 clip 函数的示例。

    func clip(imageView: UIView, withOffset offset: CGFloat) {
        let path = UIBezierPath()
    
        //Move to Top Left
        path.move(to: .init(x: imageView.bounds.size.width * offset, y: 0))
    
        //Draw line from Top Left to Top Right
        path.addLine(to: .init(x: imageView.bounds.size.width, y: 0))
    
        //Draw Line from Top Right to Bottom Right
        path.addLine(to: .init(x: imageView.bounds.size.width * (1 - offset), y: imageView.bounds.size.height))
    
        //Draw Line from Bottom Right to Bottom Left
        path.addLine(to: .init(x: 0, y: imageView.bounds.size.height))
    
        //Close Path
        path.close()
    
        //Create the Shape Mask for the ImageView
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = path.cgPath
        shapeLayer.fillColor = UIColor.black.cgColor
        imageView.layer.mask = shapeLayer
    }
    

    在此函数中,偏移量是您希望形状上的角度量,范围从 0 到 1。(0.4)似乎可以满足您的要求。

    这与 Apseri 的答案有很多相似之处,只是我选择了百分比路线,而不是确切的大小。这两种方法都没有错,我只是发现使用百分比更容易理解。 :)

    最后一点要指出,我在layoutSubviews 函数中使用了这个函数。

    override func layoutSubviews() {
        super.layoutSubviews()
        imageView.layoutIfNeeded()
        clip(imageView: self.imageView, withOffset: 0.4)
    }
    

    这会输出以下图像:

    希望这会有所帮助。

    【讨论】:

    • 您好,谢谢您的回答。但是,你为什么用layoutSubviews()
    • 因为我使用自动布局约束来设置我的视图。在 layoutSubviews 之前,imageView 不知道它的框架大小。因此,框架将为零,并且该功能将不起作用。 :)
    • layoutifNeeded() 不给出帧大小吗?
    • 嗯,原来我错了。我的印象是 layoutIfNeeded 只是通知 UI 更新。如果您愿意,我可以编辑答案。我只是将 layoutIfNeeded 和函数调用移到(我假设)表格单元格的 init 中。
    【解决方案2】:

    这里是一些路径裁剪的例子。当然path也可以通过参数来放置,这样就可以应用到任何view上,如图所示。

    之前:

    之后(灰色背景在 ScrollView 背景下方):

    func customImageClipper(imageV: UIView){
    
        let path = UIBezierPath()
        let size = imageV.frame.size
    
        path.move(to: CGPoint(x: size.width/3.0, y: 0))
        path.addLine(to: CGPoint(x: size.width/3.0 + 50, y: 0))
        path.addLine(to: CGPoint(x: size.width/3.0, y: size.height))
        path.addLine(to: CGPoint(x: size.width/3.0 - 50, y: size.height))
        path.addLine(to: CGPoint(x: size.width/3.0, y: 0))
        path.close()
    
        let shape = CAShapeLayer()
        shape.path = path.cgPath
        shape.fillColor = UIColor.black.cgColor
    
        imageV.layer.mask = shape
    }
    

    【讨论】:

      【解决方案3】:

      1- 继承你的 UIImageView

      2- 使用 UIBezierPath 在 setNeedsLayout 中实现您的自定义绘图

      class MyCustomImageView: UIImageView {  
      
      
      
          override func setNeedsLayout() {
              let path = UIBezierPath()
              path.moveToPoint(CGPoint(x: self.frame.size.width/2, y: self.frame.size.height))
              path.addLineToPoint(CGPoint(x: self.frame.size.width, y: self.frame.size.height/2))
              path.addLineToPoint(CGPoint(x: self.frame.size.width/2, y: 0))
              path.addArcWithCenter(CGPoint(x: self.frame.size.width/2, y: self.frame.size.height/2), radius: self.frame.size.width/2, startAngle:-CGFloat(M_PI_2), endAngle: CGFloat(M_PI_2), clockwise: false)
      
              path.moveToPoint(CGPoint(x: self.frame.size.width/2, y: self.frame.size.height))
              path.closePath()
              UIColor.redColor().setFill()
              path.stroke()
              path.bezierPathByReversingPath()
              let shapeLayer = CAShapeLayer()
              shapeLayer.frame = self.bounds
              shapeLayer.path = path.CGPath
              shapeLayer.fillColor = UIColor.redColor().CGColor
              self.layer.mask = shapeLayer;
              self.layer.masksToBounds = true;
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-12
        • 2021-12-07
        • 1970-01-01
        • 2014-07-17
        • 1970-01-01
        • 2022-01-23
        相关资源
        最近更新 更多