【问题标题】:Creating a shadow for a UIImageView that has rounded corners?为具有圆角的 UIImageView 创建阴影?
【发布时间】:2017-05-19 10:24:23
【问题描述】:

我正在尝试创建一个具有圆角和阴影的ImageView,以赋予它一些深度。我能够为UIImageView 创建一个阴影,但是每当我添加代码以使其具有圆角时,它只有没有阴影的圆角。我有一个名为myImageIBOutlet,它位于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
}

【问题讨论】:

  • 如果您设置clipsToBounds = true,您将永远无法看到超出范围的阴影。
  • 我建议将myImage 放在另一个不会剪裁其边界的视图中,并将阴影应用到该视图。
  • 那么只需设置 clipsToBounds = false ?
  • Clips to bounds 设置为 true 将剪切角,但会剪切阴影。这就是为什么你需要两个视图。一个带有阴影的容器,我剪裁了边界,里面有一个带有剪裁边界和圆角半径的图像。
  • 所以如果我理解正确的话,将myImage 放在一个没有剪角并且有阴影的新 UIView 中??

标签: ios swift uiview uiimageview shadow


【解决方案1】:

如果您将clipsToBounds 设置为true,这将使角落变圆,但不会出现阴影。为了解决这个问题,您可以创建两个视图。容器视图应该有阴影,它的子视图应该有圆角。

容器视图将clipsToBounds 设置为false,并应用了阴影属性。如果您还希望阴影圆润,请使用UIBezierPath 构造函数,该构造函数接受roundedRectcornerRadius

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)

结果应该是这样的:

【讨论】:

  • 我试过了,现在它有一个阴影,但是每当我设置 clipsToBounds = false 时,uiImageView 都不会四舍五入
  • 非常感谢!
  • @KevinHawk 默认情况下,UIView 的背景颜色是清晰的。如果在storyboard中创建,背景色默认为白色,需要说明清楚。同样在 Swift 中也不需要分号。
  • 很好的答案!
  • 是的!终于找到了简单的答案!
【解决方案2】:

这是 swift 2.0 中的另一个解决方案(测试代码)

如果您将 clipsToBounds 设置为 true,这将使角落变圆,但不会出现阴影。因此,您可以在 imageview 后面的故事板中添加相同大小的 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】:

    您可以使用我创建的一个简单类直接从 Storyboard 中添加带圆角和阴影的图像

    你可以找到班级here

    【讨论】:

      【解决方案4】:

      斯威夫特 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. 在该 UIView 中拖动一个 ImageView

      故事板应如下所示:

      1. 为两个视图创建 IBOutlet,在 ImageView 上调用扩展,并将上面创建的 UIView 作为参数传递。

      这是输出:

      【讨论】:

        【解决方案5】:

        最后是怎么做的

        正确的图像视图,圆角和阴影。

        就这么简单:

        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. 使用 蒙版

          对图像层进行四舍五入
        4. 要使阴影层变圆,请使用 路径

        对于阴影质量,显然添加您认为合适的代码

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

        对于实际形状(bez 路径),将其设置为您想要的任何形状。

        (例如这个技巧https://stackoverflow.com/a/41553784/294884 展示了如何只使一两个角变圆。)

        总结:

        • 在 UIView 上使用两个图层

        让你的贝塞尔曲线和...

        • 在图像层上使用蒙版

        • 在阴影层上使用路径

        【讨论】:

        • 我相信苹果对 UIImageView 进行了相当彻底的优化以显示图像。尽管我无法确认,但这种方法可能不会产生相同数量的性能。你知道吗?
        猜你喜欢
        • 1970-01-01
        • 2023-03-23
        • 2023-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-12
        相关资源
        最近更新 更多