iOS Quick Tips – Fading in a UIView with a transparent background, but not transparent contents

For March’s (slightly delayed) app, I wanted to fade in a UIView. Easy enough, right? Well, the catch was that I wanted the background to be partially transparent, but I didn’t want the contents of the view to be transparent.
My first attempt was simply to animate the view’s alpha value from 0 to 1:

view.alpha = 0;

[UIView beginAnimations:@"fade in" context:nil];
[UIView setAnimationDuration:3.0];
view.alpha = 0.5;
[UIView commitAnimations];

This didn’t quite do the trick; although the view’s background was transparent, so were its contents. Oops!

After doing some searching, I found a StackOverflow post which suggested to use colorWithAlphaComponent to set the view’s background color, instead setting the view’s alpha. So here was attempt #2:

[view setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:0]];

[UIView beginAnimations:@"fade in" context:nil];
[UIView setAnimationDuration:3.0];
[view setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:0.5]];
[UIView commitAnimations];

This wasn’t quite right either. The view’s contents appeared fully opaque as soon as the view was displayed, before the background had faded in!

So, to fix this problem, all we have to do is use a combination of the methods. Use colorWithAlphaComponent to fade in the view’s background, and use alpha to fade in the contents of the view:

[view setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:0]];
label.alpha = 0;

[UIView beginAnimations:@"fade in" context:nil];
[UIView setAnimationDuration:3.0];
label.alpha = 1.0;
[view setBackgroundColor:[[UIColor blackColor] colorWithAlphaComponent:0.5]];
[UIView commitAnimations];

Success!

Of course, you can’t actually see the fade in animation in the screenshots, so here’s a sample project that demonstrates the problems and the solution.
Download the Sample Project

7 Comments

  1. Here are a couple of observations:

    1) In method 1 (from your demo project) you’re using UIView class animation methods AND block animation methods. I would totally not recommend using both of these (in fact, while the UIView class animation methods are not deprecated, you shouldn’t be using them as per Apple: “Use of this method is discouraged in iOS 4.0 and later. You should use the block-based animation methods to specify your animations instead.”) Using both at the same time leads to ambiguity as we don’t know how these methods work internally.

    2) The best approach for something like this would be to set up your UIView hierarchy to be exactly how you want it when finished and then animate the .alpha property of the outermost view.

    It looks like that is mostly what you did although this is how I would write your 3rd method:

    {
    view.alpha = 0;
    label.alpha = 1;
    view.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:MaxAlpha];
    label.text = @”This is good!”;
    [UIView animateWithDuration:3.0 animations:^{ view.alpha = 1.f; }];
    }

    Thinking about your UIView as a hierarchy helps a lot too. You have a UIView (that has an alpha property *and* a background color that has an alpha component), with a subView (a UILabel that is itself a UIView with alpha and background color properties as well as text with color properties that contain alpha components.) The opacity of the parent view is going to control how the subviews look however the subviews are configured.

    For example, say I have a UIView with an .alpha of .5. Inside this I have another UIView that has a background color of red with alpha component of .5. If this whole thing’s superview has a white background, we’re going to be seeing that red at basically .25 (it starts with .5 opacity and that gets chopped in half by it’s superview.)

    Does this confuse things?

    I hope I understood your question correctly and that this helps!

    Reply

  2. Hey Jeff, thanks for the fantastic feedback!

    #1 – good catch! I missed the part in the docs about block-based animation being the recommended method. I will have to switch over to them. I am still new to blocks, but they seem like pretty much the same thing as lambdas or anonymous methods in .NET, so they do make quite a bit of sense.

    #2 – Thanks for the code snippet; I plugged it into my demo project and it had exactly the effect I was looking for.

    And thanks for the demo project, it really helped to wrap my brain around the view hierarchy/alpha relationship! Having a visual tool to demonstrate it was a huge help.

    Cheers!

    Reply

  3. What i did to simplify these animations (with watever content you have) is to add an overlay subview and animate the opacity of that layer:

    Dip to black -> black layer
    Flash with white -> white layer
    Fade from background -> background color layer

    One effect serves all. Saves from animating the opacity of all views and labels.

    Reply

Leave a Reply to Jeff Cancel reply

Your email address will not be published. Required fields are marked *