Подтвердить что ты не робот

Невозможно установить cornerRadius AND shadow на слой, который имеет изображение, растянутое до его границ?

Это толкает меня. У меня есть UIView (назовите его "parent" ). В нижней части этого представления находится UIImageView (назовите его "child" ), чей фрейм занимает всю полноту "родительских" границ.

Я хочу обогнуть углы на "родительском" представлении и установить тень. Я делаю это на CALayer "родителя", как обычно:

[[parent layer] setShadowOffset:CGSizeMake(5, 5)];
[[parent layer] setShadowRadius:6];
[[parent layer] setShadowOpacity:0.4];    
[[parent layer] setCornerRadius:6];

Это показывает тень правильно, но не вокруг углов.

Здесь кикер:

  • Если я удаляю представление "дочерний" образ или сокращаю его, чтобы он не занимал все границы "родительского" представления, я получаю закругленные углы и тень правильно на родительском объекте.
  • Если я оставляю только "ребенка", но устанавливаю "clipToBounds" в "родительском" представлении, я правильно получаю углы. Но теперь тень ушла.
  • Настройка радиуса угла на слое ребенка также не имеет эффекта.

Похоже, что "образ ребенка" просто скрывает закругленные углы на "родительском" представлении, так как он занимает весь прямоугольник, а обрезка на основе родительского представления получает углы, но также маскирует тень. Не знаете, почему № 3 не работает.

Что мне не хватает? Разве я не замечал ничего очевидного, слишком долго смотрел на это?

Спасибо.

(Потрясающе, тег "roundedcorners-dropshadow" уже существует. Awesome.)

4b9b3361

Ответ 1

Вам понадобятся два вложенных вида, внутренний - с закругленными углами и отсечением для привязки, а внешний вид имеет тень (и, следовательно, не отсекает). В вашем случае внутренний и внешний вид, вероятно, будут "child" и "parent", но я думаю, вы не установили правильные значения отсечения для этих представлений?

См. ответ в Почему masksToBounds = YES предотвращает тень CALayer?.

Ответ 2

Как правило, вы должны установить clipToBounds для округлых углов, но поскольку вы хотите сохранить тень, вы также должны окружать углы тени. Пробовали ли вы установить путь тени, используя путь безье? Держите клипсыToBounds/masksToBounds по умолчанию, NO. Что-то вроде:

  [[parent layer] setCornerRadius:6.0f];
  [[parent layer] setShadowPath:
             [[UIBezierPath bezierPathWithRoundedRect:[parent bounds] 
                   cornerRadius:6.0f] CGPath]];

Ответ 3

Вы пытались установить границы дочернего UIImageView так, чтобы он также имел закругленные углы? Возможно, тогда он не переопределит тень контейнера. Просто мысль, не уверен, что это сработает.

Ответ 4

С помощью Swift 3 вы можете выбрать один из двух следующих фрагментов кода, чтобы установить cornerRadius и тень на изображении или в представлении, содержащем слой изображения.


# 1. Используя UIView, CALayer и Spring и Struts

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // constants
        let radius: CGFloat = 20, dimension: CGFloat = 200, offset = 8
        let frame = CGRect(x: 0, y: 0, width: 200, height: 200)

        // custom view
        let customView = UIView(frame: frame)
        customView.contentMode = .scaleAspectFill

        // image layer
        let imageLayer = CALayer()
        imageLayer.contentsGravity = kCAGravityResizeAspectFill
        imageLayer.contents = UIImage(named: "image")!.cgImage
        imageLayer.masksToBounds = true
        imageLayer.frame = frame
        imageLayer.cornerRadius = radius
        imageLayer.masksToBounds = true

        // rounded layer
        let roundedLayer = CALayer()
        roundedLayer.shadowColor = UIColor.darkGray.cgColor
        roundedLayer.shadowPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: dimension, height: dimension), cornerRadius: radius).cgPath
        roundedLayer.shadowOffset = CGSize(width: offset, height: offset)
        roundedLayer.shadowOpacity = 0.8
        roundedLayer.shadowRadius = 2
        roundedLayer.frame = frame

        // views and layers hierarchy
        customView.layer.addSublayer(imageLayer)
        customView.layer.insertSublayer(roundedLayer, below: imageLayer)
        view.addSubview(customView)

        // layout
        customView.center = CGPoint(x: view.bounds.midX, y: view.bounds.midY)
        customView.autoresizingMask = [UIViewAutoresizing.flexibleLeftMargin, .flexibleRightMargin, .flexibleTopMargin, .flexibleBottomMargin]
    }

}

# 2. Используя UIView, UIImageView, CALayer и автоматический макет

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // constants
        let radius: CGFloat = 20, dimension: CGFloat = 200, offset = 8

        // image view
        let imageView = UIImageView(image: UIImage(named: "image"))
        imageView.contentMode = .scaleAspectFill
        imageView.layer.cornerRadius = radius
        imageView.layer.masksToBounds = true

        // rounded view
        let roundedView = UIView()
        roundedView.layer.shadowColor = UIColor.darkGray.cgColor
        roundedView.layer.shadowPath = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: dimension, height: dimension), cornerRadius: radius).cgPath
        roundedView.layer.shadowOffset = CGSize(width: offset, height: offset)
        roundedView.layer.shadowOpacity = 0.8
        roundedView.layer.shadowRadius = 2

        // views hierarchy
        roundedView.addSubview(imageView)
        view.addSubview(roundedView)

        // layout
        imageView.translatesAutoresizingMaskIntoConstraints = false
        roundedView.translatesAutoresizingMaskIntoConstraints = false
        roundedView.widthAnchor.constraint(equalToConstant: dimension).isActive = true
        roundedView.heightAnchor.constraint(equalToConstant: dimension).isActive = true
        imageView.widthAnchor.constraint(equalTo: roundedView.widthAnchor).isActive = true
        imageView.heightAnchor.constraint(equalTo: roundedView.heightAnchor).isActive = true
        roundedView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        roundedView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        imageView.centerXAnchor.constraint(equalTo: roundedView.centerXAnchor).isActive = true
        imageView.centerYAnchor.constraint(equalTo: roundedView.centerYAnchor).isActive = true
    }

}

Оба фрагмента кода генерируют следующий экран:

введите описание изображения здесь


Вы можете найти больше способов комбинировать изображения с закругленными углами и тенью на этом Github repo.