Как создать в Swift круглое профильное изображение или закругленное Угловое Изображение с границей, которая не протекает?

на основе исходный код ниже:

    @IBOutlet var myUIImageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.makingRoundedImageProfileWithRoundedBorder()
    }

    private func makingRoundedImageProfileWithRoundedBorder() {    
        // Making a circular image profile.
//        self.myUIImageView.layer.cornerRadius = self.myUIImageView.frame.size.width / 2
        // Making a rounded image profile.
        self.myUIImageView.layer.cornerRadius = 20.0

        self.myUIImageView.clipsToBounds = true

        // Adding a border to the image profile
        self.myUIImageView.layer.borderWidth = 10.0
        self.myUIImageView.layer.borderColor = UIColor.whiteColor().CGColor
    }

действительно, я могу отобразить круговой или округленный UIImageView, но проблема в том, что если мы добавим границу, изображение немного утечет. Это намного хуже с круговым UIImageView, он протекает всякий раз, когда граница согнута, поэтому протекает везде! Вы можете найти скриншот результата ниже:

UIImageView rendered

любой способ исправить это в Swift? Любой пример кода, который отвечает на этот вопрос, будет высоко оценить.

Примечание: насколько это возможно, решение должно быть совместимо с iOS 7 и 8+.

3 ответов


Первый Вариант

основываясь на предложении @Jesper Schläger

"если я могу предложить быстрое и грязное решение:

вместо добавления границы в представление изображения, вы можете просто добавить еще один белый вид под видом изображения. Сделайте вид расширенным на 10 точек в любом направлении и дайте ему радиус угла 20.0. Дайте виду изображения радиус угла 10.0."

вы можете найти Свифт реализация ниже:

import UIKit

class ViewController: UIViewController {

   @IBOutlet var myUIImageView: UIImageView!

   @IBOutlet var myUIViewBackground: UIView!

   override func viewDidLoad() {
        super.viewDidLoad()

        // Making a circular UIView: cornerRadius = self.myUIImageView.frame.size.width / 2
        // Making a rounded UIView: cornerRadius = 10.0
        self.roundingUIView(self.myUIImageView, cornerRadiusParam: 10)
        self.roundingUIView(self.myUIViewBackground, cornerRadiusParam: 20)
   }

   private func roundingUIView(let aView: UIView!, let cornerRadiusParam: CGFloat!) {
       aView.clipsToBounds = true
       aView.layer.cornerRadius = cornerRadiusParam
   }

}

Второй Вариант

было бы установить маску круга над CALayer.

вы можете найти С реализация этого второго решения ниже:

CALayer *maskedLayer = [CALayer layer];
[maskedLayer setFrame:CGRectMake(50, 50, 100, 100)];
[maskedLayer setBackgroundColor:[UIColor blackColor].CGColor];

UIBezierPath *maskingPath = [UIBezierPath bezierPath];
[maskingPath addArcWithCenter:maskedLayer.position
                       radius:40
                   startAngle:0
                     endAngle:360
                    clockwise:TRUE];

CAShapeLayer *maskingLayer = [CAShapeLayer layer];
[maskingLayer setPath:maskingPath.CGPath];

[maskedLayer setMask:maskingLayer];
[self.view.layer addSublayer:maskedLayer];

если вы прокомментируете из строки UIBezierPath *maskingPath = [UIBezierPath bezierPath]; через [maskedLayer setMask:maskingLayer]; вы увидите, что слой представляет собой квадрат. Однако, когда эти линии не комментируются, слой представляет собой круг.

примечание: Я не тестировал это второе решение не обеспечило быструю реализацию, поэтому не стесняйтесь тестировать его и дайте мне знать, работает ли он или нет через раздел комментариев ниже. Также не стесняйтесь редактировать этот пост, добавляя быструю реализацию этого второго решения.


Если я могу предложить быстрое и грязное решение:

вместо добавления границы в представление изображения, вы можете просто добавить еще один белый вид под видом изображения. Сделайте вид расширенным на 10 точек в любом направлении и дайте ему радиус угла 20.0. Дайте виду изображения радиус угла 10.0.


Я работал над улучшением кода, но он продолжает сбой. Я буду работать над этим, но у меня, похоже, есть (грубая) версия:

редактировать обновлено с немного более приятной версией. Мне не нравится init:coder метод, но, возможно, это может быть учтено/улучшено

class RoundedImageView: UIView {
    var image: UIImage? {
        didSet {
            if let image = image {
                self.frame = CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale)
            }
        }
    }
    var cornerRadius: CGFloat?

    private class func frameForImage(image: UIImage) -> CGRect {
        return CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale)
    }

    override func drawRect(rect: CGRect) {
        if let image = self.image {
            image.drawInRect(rect)

            let cornerRadius = self.cornerRadius ?? rect.size.width/10
            let path = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius)
            UIColor.whiteColor().setStroke()
            path.lineWidth = cornerRadius
            path.stroke()
        }
    }
}

let image = UIImage(named: "big-teddy-bear.jpg")

let imageView = RoundedImageView()
imageView.image = image

Дайте мне знать, если это то, что вы ищете.

небольшое пояснение:

как я уверен, вы нашли, "граница", которую iOS может применить, не является замечательно, и показывает углы по какой-то причине. Я нашел несколько других решений, но ни одно из них не сработало. Причина в том, что это подкласс UIView, а не UIImageView, это drawRect: не вызывается для подклассов UIImageView. Я не уверен в производительности этого кода, но он кажется хорошим от моего (ограниченного) тестирования

исходный код:

class RoundedImageView: UIView {

    var image: UIImage? {
        didSet {
            if let image = image {
                self.frame = CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale)
            }
        }
    }

    private class func frameForImage(image: UIImage) -> CGRect {
        return CGRect(x: 0, y: 0, width: image.size.width/image.scale, height: image.size.width/image.scale)
    }

    override func drawRect(rect: CGRect) {
        if let image = self.image {
            self.image?.drawInRect(rect)

            let path = UIBezierPath(roundedRect: rect, cornerRadius: 50)
            UIColor.whiteColor().setStroke()
            path.lineWidth = 10
            path.stroke()
        }
    }
}

let image = UIImage(named: "big-teddy-bear.jpg")

let imageView = RoundedImageView()
imageView.image = image
imageView.layer.cornerRadius = 50
imageView.clipsToBounds = true