Как добавить пользовательскую фигуру в UIImageView в Swift? - PullRequest
5 голосов
/ 11 января 2020

Я пытаюсь добавить пользовательскую фигуру к 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)

PS: я не использую Storyboard, я создал это программно.

Ответы [ 3 ]

2 голосов
/ 14 января 2020

Существует множество способов создания фигур с использованием 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's. Ответ, кроме того, что я выбрал маршрут процентов, а не точный размер. Ничего плохого ни в одном из подходов, мне просто было легче понять с процентами. :)

Последнее замечание: я использовал эту функцию в функции layoutSubviews.

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

Это выдает следующее изображение:

Image of a cell showing custom shape

Надеюсь, это поможет.

2 голосов
/ 14 января 2020

Вот пример некоторого отсечения пути. Конечно, путь может быть также задан через параметры, и это может быть применено к любому представлению, как показано.

До:

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 голосов
/ 20 января 2020

1 - создание подклассов вашего UIImageView

2 - внедрение ваших пользовательских чертежей в setNeedsLayout с использованием UIBezierPath

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

}
...