I know how to do (1) but how can I do (2)?
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)];
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view.bounds;
gradient.colors = @[(id)[UIColor blueColor].CGColor, (id)[UIColor redColor].CGColor];
[view.layer insertSublayer:gradient atIndex:0];
There are several ways you could do this. Here's one way:
Create a
UIView
subclass namedGradientView
to manage the gradient layer. This is helpful because it means you can use the normal UIKit techniques to manage the gradient layout (auto layout constraints, autoresizing masks, UIKit animations).For each view that should participate in the common gradient, add a
GradientView
subview. Set up eachGradientView
's colors, locations, and start and end points identically.For each view that should participate in the common gradient, turn on
clipsToBounds
.Use auto layout constraints to make each
GradientView
span all of the participating superviews. (It's important to understand that constraints can cross superview/subview boundaries).With this approach, auto layout takes care of making the gradient cover all of the views even if they change size or move around. For example, you won't have to do anything special to make the gradients animate nicely when the user rotates the device.
Thus, for your two-view example, I'm proposing that you set up a view hierarchy like this:
In the view debugger screenshot above, I disabled clipping. You can see that the two gradient views have identical gradients and share the same screen space. The
topGradient
is a subview oftopView
andbottomGradient
is a subview ofbottomView
.If we turn clipping on, you'll only see the part of
topGradient
that fits insidetopView
's bounds, and you'll only see the part ofbottomGradient
that fits insidebottomView
's bounds. Here's what it looks like with clipping enabled:And here's a screen shot of my test program in the simulator:
Here's the source code for
GradientView
:Here's the code I used to create all of the views:
And here's how I create the constraints that make a
GradientView
(or any view) cover a set of views:The
greaterThanOrEqual
/lessThanOrEqual
constraints, which (by default) have required priority, ensure thatcoverer
covers the entire frame of eachcoveree
. Theequal
constraints, which have lower priority, then ensure thatcoverer
occupies the minimum space required to cover eachcoveree
.You can do this by adding a view on top of the view with the gradient, then cutting out the shapes by making a mask out of a
UIBezierPath
, then adding that to the view on top (let's call ittopView
):