如何在Swift中将自定义形状添加到UIImageView?

5
我正在尝试将自定义形状添加到一个 imageView 中。请查看下面的图片。
这是所需的形状:

Required Image Shape

这是我目前为止所做的:

Current Image Shape

我是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)

附言:我没有使用Storyboard,我是通过编程创建的。

3个回答

6

使用UIBezierPaths有多种方法创建形状。 这篇文章讨论了使用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() - Rob13
因为我使用了自动布局约束来设置视图。在 layoutSubviews 之前,imageView 不知道它的 frame 大小是多少。因此,frame 将为零,函数将无法工作。 :) - Paulo
layoutIfNeeded() 不是会给出框架大小吗? - Rob13
嗯,事实证明我错了。我一直以为layoutIfNeeded只是通知UI更新。如果您愿意,我可以编辑答案。我只是将layoutIfNeeded和函数调用移动到(我认为的)表格单元格的init中。 - Paulo

2

以下是一些路径裁剪的示例。当然,路径也可以通过参数设置,并且可以应用于任何视图,如所示。

之前:

enter image description here

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

enter image description here

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
}

0

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;
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接