在UIView之外画阴影

Lin*_*rth 5 shadow dropshadow ios swift

背景

我有UIView以下属性:

  • alpha = 1
  • backgroundColor = white,0.35不透明度
  • 圆角
  • 投影

这是我创建投影的方式:( UIView扩展名)

self.layer.masksToBounds = false
self.layer.shadowColor = UIColor.darkGrayColor().CGColor
self.layer.shadowOffset = CGSizeMake(0, 5)
self.layer.shadowOpacity = 0.35
self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.layer.cornerRadius).CGPath
Run Code Online (Sandbox Code Playgroud)

结果

这导致以下结果:

目前的结果

...虽然我不想看到视图下面的阴影,如下所示:

希望结果

如何在视图外部绘制阴影,使其在下方不可见?

提前致谢!

xou*_*ini 6

这可能比它需要的稍微复杂一些,但这是一个解决方案.

UIView使用以下方法扩展:

extension UIView {
    // Note: the method needs the view from which the context is taken as an argument.
    func dropShadow(superview: UIView) {
        // Get context from superview
        UIGraphicsBeginImageContext(self.bounds.size)
        superview.drawViewHierarchyInRect(CGRect(x: -self.frame.minX, y: -self.frame.minY, width: superview.bounds.width, height: superview.bounds.height), afterScreenUpdates: true)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        // Add a UIImageView with the image from the context as a subview
        let imageView = UIImageView(frame: self.bounds)
        imageView.image = image
        imageView.layer.cornerRadius = self.layer.cornerRadius
        imageView.clipsToBounds = true
        self.addSubview(imageView)

        // Bring the background color to the front, alternatively set it as UIColor(white: 1, alpha: 0.2)
        let brighter = UIView(frame: self.bounds)
        brighter.backgroundColor = self.backgroundColor ?? UIColor(white: 1, alpha: 0.2)
        brighter.layer.cornerRadius = self.layer.cornerRadius
        brighter.clipsToBounds = true
        self.addSubview(brighter)

        // Set the shadow
        self.layer.masksToBounds = false
        self.layer.shadowColor = UIColor.darkGrayColor().CGColor
        self.layer.shadowOffset = CGSizeMake(0, 5)
        self.layer.shadowOpacity = 0.35
        self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.layer.cornerRadius).CGPath
    }
}
Run Code Online (Sandbox Code Playgroud)

用法,考虑到后台视图命名view:

let shadowView = UIView(frame: CGRect(x: 100, y: 100, width: 300, height: 200))
shadowView.layer.cornerRadius = 15.0
shadowView.dropShadow(view)

view.addSubview(shadowView)
Run Code Online (Sandbox Code Playgroud)

这导致了这样的观点:

的UIView

注:dropShadow方法不能从所谓的viewDidLoad,因为这会导致与图形上下文的问题.因此,viewWillAppear最早使用此方法获得上述结果.


这是背景视图的代码,以防万一有人想在游乐场测试:

let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 400))
view.backgroundColor = UIColor.clearColor()

let color1 = UIColor(hue: 0.39, saturation: 0.7, brightness: 1.0, alpha: 1.0).CGColor
let color2 = UIColor(hue: 0.51, saturation: 0.9, brightness: 0.6, alpha: 1.0).CGColor

let gradient = CAGradientLayer()
gradient.frame = view.frame
gradient.colors = [color1, color2]
gradient.startPoint = CGPoint(x: 0, y: 0)
gradient.endPoint = CGPoint(x: 1, y: 1)
view.layer.insertSublayer(gradient, atIndex: 0)
Run Code Online (Sandbox Code Playgroud)


kan*_*ius 6

我通常使用视图组合来解决这种情况。target我没有在视图中设置阴影,而是创建一个ShadowView阴影并将其放在target视图后面,具有相同的框架。

这样做,我们可以遮盖阴影视图,以便仅在其框架之外绘制阴影。

阴影蒙版的代码是(上面的完整代码):

      let maskLayer = CAShapeLayer()
      let path = CGMutablePath()
      path.addPath(UIBezierPath(roundedRect: bounds.inset(by: UIEdgeInsets.zero), cornerRadius: CGFloat(cornerRadius)).cgPath)
      path.addPath(UIBezierPath(roundedRect: bounds.inset(by: UIEdgeInsets(top: -offset.height - radius*2, left: -offset.width - radius*2, bottom: -offset.height - radius*2, right: -offset.width - radius*2)), cornerRadius: CGFloat(cornerRadius)).cgPath)
      maskLayer.backgroundColor = UIColor.black.cgColor
      maskLayer.path = path;
      maskLayer.fillRule = .evenOdd
      self.layer.mask = maskLayer
Run Code Online (Sandbox Code Playgroud)

结果如下:

蒙面阴影

完整的游乐场可以在这里: https://gist.github.com/llinardos/d1ede3b491efc8edac940c5ea8631c6f

这种效果在背景模糊的情况下看起来非常好。