Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
698 views
in Technique[技术] by (71.8m points)

ios - Swift - Cut hole in shadow layer

I want to "cut a hole" in the shadow layer of a UIView an Swift3, iOS

I have a container (UIView), that has 2 children:

  • one UIImageView
  • one UIView on top of that image ("overlay")

I want to give the overlay a shadow and cut out an inner rect of that shadow, to create a glow-like effect at the edges of the ImageView
It is crucial that the glow is inset, since the image is taking the screen width
My code so far:

let glowView = UIView(frame: CGRect(x: 0, y: 0, width: imageWidth, height: imageHeight))
glowView.layer.shadowPath = UIBezierPath(roundedRect: container.bounds, cornerRadius: 4.0).cgPath
glowView.layer.shouldRasterize = true
glowView.layer.rasterizationScale = UIScreen.main.scale
glowView.layer.shadowOffset = CGSize(width: 1.0, height: 1.0)
glowView.layer.shadowOpacity = 0.4

container.addSubview(imageView)
container.addSubview(glowView)

The result looks like the following right now:

image

Now I would like to cut out the darker inner part, so that just the shadow at the edges remains
Any idea how to achieve this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Fortunately it's now very easy today (2020)

These days it's very easy to do this:

enter image description here

Here's the whole thing

import UIKit
class GlowBox: UIView {
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        backgroundColor = .clear
        layer.shadowOpacity = 1
        layer.shadowColor = UIColor.red.cgColor
        layer.shadowOffset = CGSize(width: 0, height: 0)
        layer.shadowRadius = 3
        
        let p = UIBezierPath(
             roundedRect: bounds.insetBy(dx: 0, dy: 0),
             cornerRadius: 4)
        let hole = UIBezierPath(
             roundedRect: bounds.insetBy(dx: 2, dy: 2),
             cornerRadius: 3)
             .reversing()
        p.append(hole)
        layer.shadowPath = p.cgPath
    }
}

A really handy tip:

When you add (that is .append ) two bezier paths like that...

The second one has to be either "normal" or "reversed".

Notice the line of code near the end:

             .reversing()

Like most programmers, I can NEVER REMEMBER if it should be "normal" or "reversed" in different cases!!

The simple solution ...

Very simply, try both!

Simply try it with, and without, the .reversing()

It will work one way or the other! :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...