Alex Stone
Alex Stone

Reputation: 47348

iOS - how to create a "material design" compliant UIView with shadow?

I'm trying to see if there's a way to create a UIView with a shadow behavior compliant with material design. My understanding is that the shadow gets more intense as the object is further removed from the background surface.

I can manually add a shadow like this, however this shadow does not calculate how intense the shadow should be (based on Z order).

    button.layer.shadowPath = [UIBezierPath bezierPathWithRoundedRect:button.layer.bounds cornerRadius:11].CGPath;
    button.layer.shadowOpacity = 1.0;
    button.layer.shadowOffset = CGSizeMake(1,1);
    button.layer.shadowColor = [UIColor blackColor].CGColor;

How do I create a UIView which will behave like Google's material design? I found this example, called Material Kit, however it simply hides shadow on touch

One way in which Google does this is by emphasizing the use of a ‘z-axis’ to create a sense of depth in which elements can occupy different levels. In order to show that an element is occupying a higher level on the z-axis, shadows are used around its border, being cast on to the level below. What this creates is the illusion of an interactive layer/element that exists above a different, lower interactive layer/element.

enter image description here

Upvotes: 5

Views: 4349

Answers (2)

Dimitris
Dimitris

Reputation: 1

In order to apply both a shadow and a rounded corner, you need to use 2 nested views. This is because the two effects require competing masksToBounds properties.

Nest 2 UIViews. Apply the shadow to the outer view, setting masksToBounds = false. Then apply the rounded corner to the inner view, which requires masksToBounds = true.

Note that, according to Apple docs, masksToBounds is equivalent to clipsToBounds.

Upvotes: 0

Rufel
Rufel

Reputation: 2660

You could subclass UIButton, and first set the shadow properties to your liking:

button.layer.shadowOffset = CGSizeMake(0, 1);
button.layer.shadowRadius = 5;
button.layer.shadowOpacity = 0;

Then change the shadowOpacity property when the highlighted state changes:

- (void)setHighlighted:(BOOL)highlighted
{
    [super setHighlighted:highlighted];
    self.layer.shadowOpacity = (highlighted ? 0.85 : 0);
}

Upvotes: 7

Related Questions