简体   繁体   中英

Reload UIView gradient background

I have set my UIView background colour to a CAGradient layer which works well. I am trying to change this gradient within the application when it is running. If i close and reload the app the new gradient is applied but i want this to work during run time.

CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.backGroundView.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor whiteColor] CGColor], color.CGColor, nil];

[self.backGroundView.layer insertSublayer:gradient atIndex:0];

[self.backGroundView setNeedsDisplay];
self.backGroundView.contentMode = UIViewContentModeRedraw;

I have tried both setNeedsDisplay and UIViewContentModeRedraw but neither are updating the UIview background while the app is running?

It looks like your gradient.colors array is not initialised properly. It's a bit of a mess on the right side :).

Sometimes a bit of verbosity is warranted, because it makes code more readable, ie you split the problem into multiple lines thus your brain is more in control because you better see what is going on. Therefore let's initialise the colors on separate line a see if it works.

    CAGradientLayer *gradient = [CAGradientLayer layer];

    CGColorRef color1 = [UIColor redColor].CGColor;
    CGColorRef color2 = [UIColor greenColor].CGColor;
    gradient.colors = @[  (__bridge id)color1  ,  (__bridge id)color2  ];

    [self.view.layer insertSublayer:gradient atIndex:0];

There's a bit of a trickery. The CoreAnimation framework expects to find CGColor objects inside the array. But the property is of NSArray type and NSArrays really is an array of "id"s, which are "dumb" pointers to any object. So we create our CGColor instances (on separate lines for sanity), and then we (using modern objective C literals for gods sake :) create the array and since you are casting CoreFoundation objects (CGColors) to Foundation object (id) it needs to be bridged.

Now you can reuse the code also in runtime, for example inside a button pressed action. Since you already have a gradient layer in layer hierarchy there already, you need to get a reference to it. (first line does it)

- (IBAction)changeColorsOnbuttonPressed:(id)sender
{
    CAGradientLayer *gradient = [self.view.layer.sublayers firstObject];

    CGColorRef color1 = [UIColor blueColor].CGColor;
    CGColorRef color2 = [UIColor yellowColor].CGColor;
    gradient.colors = @[(__bridge id)color1, (__bridge id)color2];
} 

You should not need to set the view to be dirty with setNeedsLayout and layoutIfNeeded.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM