Create shadow around a UIVisualEffectView without covering the whole view
Asked Answered
N

5

9

Is it possible to create a shadow around a UIVisualView with UIBlurEffect without letting the UIVisualView get coloured by the shadow underneath?

I basically just want the shadow around the view but with this code the shadow will cover the whole view which darkens the whole view to much:

let borderPath = UIBezierPath(roundedRect: view.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 15, height: 15)).cgPath

shadowView.frame = view.bounds
shadowView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
shadowView.layer.shadowOpacity = 0.3
shadowView.layer.shadowRadius = 3.0
shadowView.backgroundColor = UIColor.clear

shadowView.layer.shadowPath = borderPath
shadowView.layer.shadowOffset = CGSize(width: 0, height: 0)
self.view.insertSubview(shadowView, at: 0)

let blurEffect = UIBlurEffect(style: .extraLight)
let blurView = UIVisualEffectView(effect: blurEffect)
blurView.frame = view.bounds
blurView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
blurView.clipsToBounds = true
blurView.layer.cornerRadius = 15
view.insertSubview(blurView, aboveSubview: shadowView)

EDIT.
I need to achieve the same thing as in Apple's Maps application. Where the draggable favourite view both uses the UIVisualEffectView and a shadow around its top, without interfering with the UIVisualEffectView's background.

See example screenshots: enter image description here enter image description here

Nicole answered 5/10, 2016 at 23:56 Comment(2)
you can take view bellow to original view apply and apply shadow to that view. Make sure the view which you are going to set bellow to from view having same dimensionsStenosis
I don't understand what you mean. Please show me a example.Nicole
N
5

Ok, so the problem was that my background in the underlying view was white. And with the UIBlurEffect .extraLight used on a background which is lighter than the BlurEffect the shadow beneath a UIVisualView appears darker than with a more vivid background.

Also described in this question:
Fix UIVisualEffectView extra light blur being gray on white background

UPDATE

I found a project explaining how to solve this on Github The solution involves creating a 9-part UIImage to represent the shadow. The creator also explains the underlying layers of the iOS 10 Maps.

Nicole answered 8/10, 2016 at 19:40 Comment(2)
is there a solution for a white/transparent background?Femi
I guess you can try to cut the shadow so that the outer of the shadow only appears and the inner of the shadow is clear.Nicole
L
3

So i'm trying to recreate the look of iOS 10 maps. I decided to attach the maps app in the simulator to the debugger to see what was going on...

View debugger breakdown

Apple actually get around this by having a UIImage over the top of the content with the border and shadow. Not the most elegant way to do it but i'm going for the exact look so I'm going to take the exact approach.

I also grabbed the asset (using this) from the Maps app to save making your own one. Shame they only have @2x artwork in it though :/

CardShadowFull@2x.png

Leviathan answered 2/3, 2017 at 12:34 Comment(6)
Have you made any progress in recreating the iOS10 Maps in your project?Nicole
@alengqvist: I was only looking to replicate the look of this border and completed that task. One thing to note is that the asset I borrowed from the maps app has the "special" irregular corner radius so it won't line up if you just set a regular layer.cornerRadius valueLeviathan
Small question how did you attach the debugger to the Apple Map app ??Yoohoo
@MaudeBeaulac: Xcode > Menu > Debug > Attach to Process and then select whatever simulator process you want :)Leviathan
I tried this but it tels me I do not have permission.Yoohoo
@MaudeBeaulac You're targeting the simulator yeah? Can't do it on an actual deviceLeviathan
W
2

I found in iOS 12, this is not a problem, the UIVisualEffectView ignore the shadow of underneath views, it just sees through the shadow, like the shadow not exist.

Womanize answered 27/7, 2018 at 17:6 Comment(1)
I am looking at iOS 13.4 simulator, shadow does change the blurGoethite
V
1

The trick is to not set the shadowPath of the layer. If it is set, the shadow is painted below the visual effect view and, in consequence, darkens the blurred view.

The documentation for shadowPath states:

If you specify a value for this property, the layer creates its shadow using the specified path instead of the layer’s composited alpha channel.

The "instead…" part is what we actually need: the shadow should be composed after rendering the content, based on what the content leaves transparent. Now you might be deterred from not setting a shadowPath because the documentation also states that an "explicit path usually improves rendering performance". However, I didn't see any issues in real life so far. In comparison to the rendering cost of the UIVisualEffectView, painting the shadow doesn't make a difference, I assume.

Also make sure to set the shadow on a superview of the UIVisualEffectView, not on a sibling view.

Valet answered 14/11, 2018 at 12:33 Comment(0)
R
0

I usually solve this kind of situation using composition of views. Instead of setting the shadow in the target view, I create a ShadowView and I put it behind the target view, both views with the same frame.

I've posted and example and code in this question.

An example of the result of this approach is the following:

enter image description here

Razzia answered 29/5, 2019 at 1:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.