Создание тени для UIImageView с закругленными углами?

Я пытаюсь создать ImageView который имеет закругленные углы и тень, чтобы дать ему некоторую глубину. Я смог создать тень для UIImageView, но всякий раз, когда я добавлял код, чтобы он также имел закругленные углы, он имел закругленные углы без тени. У меня есть IBOutlet именем myImage, и он находится внутри функции viewDidLoad. Кто-нибудь есть идеи о том, как заставить его работать? Что я делаю не так?

override func viewDidLoad() {
    super.ViewDidLoad() 
    myImage.layer.shadowColor = UIColor.black.cgColor
    myImage.layer.shadowOpacity = 1 
    myImage.layer.shadowOffset = CGSize.zero
    myImage.layer.shadowRadius = 10
    myImage.layer.shadowPath = UIBezierPath(rect: myImage.bounds).cgPath
    myImage.layer.shouldRasterize = false
    myImage.layer.cornerRadius = 10
    myImage.clipsToBounds = true
}

Ответ 1

Если вы установите для clipsToBounds значение true, это будет вокруг углов, но не позволит появиться тень. Чтобы решить эту проблему, вы можете создать два представления. В представлении контейнера должна быть тень, а его подпункт должен иметь закругленные углы.

В представлении контейнера clipsToBounds установлены на false и применяются теневые свойства. Если вы хотите, чтобы тень также закруглялась, используйте конструктор UIBezierPath который принимает roundedRect и cornerRadius.

let outerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
outerView.clipsToBounds = false
outerView.layer.shadowColor = UIColor.black.cgColor
outerView.layer.shadowOpacity = 1
outerView.layer.shadowOffset = CGSize.zero
outerView.layer.shadowRadius = 10
outerView.layer.shadowPath = UIBezierPath(roundedRect: outerView.bounds, cornerRadius: 10).cgPath

Затем установите для представления изображения (или любого другого типа UIView) одинаковый размер представления контейнера, установите для clipsToBounds значение true и дайте ему cornerRadius.

let myImage = UIImageView(frame: outerView.bounds)
myImage.clipsToBounds = true
myImage.layer.cornerRadius = 10

Наконец, не забудьте сделать представление изображения подведомственным в виде контейнера.

outerView.addSubview(myImage)

Результат должен выглядеть примерно так:

enter image description here

Ответ 2

Вот еще одно решение (проверенный код) в Swift 2.0

Если для clipsToBounds установлено значение true, это закруглит углы, но предотвратит появление тени. Таким образом, вы можете добавить UIView того же размера в раскадровку за изображением, и мы можем дать тень этому представлению

SWIFT 2.0

outerView.layer.cornerRadius = 20.0
outerView.layer.shadowColor = UIColor.blackColor().CGColor
outerView.layer.shadowOffset = CGSizeMake(0, 2)
outerView.layer.shadowOpacity = 1
outerView.backgroundColor = UIColor.whiteColor()

Ответ 3

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

Вы можете найти класс здесь

Swift_Shadow_ImageView

Ответ 4

2019

Наконец, вот как

Правильно получайте изображение с закругленными углами и тенями.

Это так просто:

class ShadowRoundedImageView: UIView {
    @IBInspectable var image: UIImage? = nil {
        didSet {
            imageLayer.contents = image?.cgImage
            shadowLayer.shadowPath = (image == nil) ? nil : shapeAsPath }}

    var imageLayer: CALayer = CALayer()
    var shadowLayer: CALayer = CALayer()

    var shape: UIBezierPath {
        return UIBezierPath(roundedRect: bounds, cornerRadius:50) }

    var shapeAsPath: CGPath {
        return shape.cgPath }

    var shapeAsMask: CAShapeLayer {
        let s = CAShapeLayer()
        s.path = shapeAsPath
        return s }

    override func layoutSubviews() {
        super.layoutSubviews()
        clipsToBounds = false
        backgroundColor = .clear

        self.layer.addSublayer(shadowLayer)
        self.layer.addSublayer(imageLayer) // (in that order)

        imageLayer.frame = bounds
        imageLayer.contentsGravity = .resizeAspectFill // (as preferred)

        imageLayer.mask = shapeAsMask
        shadowLayer.shadowPath = (image == nil) ? nil : shapeAsPath
        shadowLayer.shadowOpacity = 0.80 // etc ...
    }
}

Вот

Объяснение

  1. UIImageView бесполезен, вы используете UIView

  2. Вам нужно два слоя, один для тени и один для изображения

  3. Для округления слоя изображения вы используете маску mask

  4. Для округления теневого слоя вы используете путь path

Для качества теней, очевидно, добавьте код, который вы считаете нужным

    shadowLayer.shadowOffset = CGSize(width: 0, height: 20)
    shadowLayer.shadowColor = UIColor.purple.cgColor
    shadowLayer.shadowRadius = 5
    shadowLayer.shadowOpacity = 0.80

Для фактической фигуры (пути без) сделайте любую фигуру, какую пожелаете.

(Например, этот совет fooobar.com/questions/28274/... показывает, как сделать только один или два угла закругленными.)

Резюме

• Используйте два слоя на UIView

Сделай свое безье и...

• Используйте маску на слое изображения

• Используйте путь на теневом слое

Ответ 5

Свифт 5:

Вы можете использовать следующее расширение:

extension UIImageView {
func applyshadowWithCorner(containerView : UIView, cornerRadious : CGFloat){
    containerView.clipsToBounds = false
    containerView.layer.shadowColor = UIColor.black.cgColor
    containerView.layer.shadowOpacity = 1
    containerView.layer.shadowOffset = CGSize.zero
    containerView.layer.shadowRadius = 10
    containerView.layer.cornerRadius = cornerRadious
    containerView.layer.shadowPath = UIBezierPath(roundedRect: containerView.bounds, cornerRadius: cornerRadious).cgPath
    self.clipsToBounds = true
    self.layer.cornerRadius = cornerRadious
}

}

Как пользоваться:

  1. Перетащите UIView на раскадровку
  2. Перетащите ImageView внутри этого UIView

Раскадровка должна выглядеть так:

enter image description here

  1. Создайте IBOutlet для просмотра, вызова расширения для вашего ImageView и передачи выше созданного UIView в качестве аргумента.

Вот вывод:

enter image description here