Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Creating an animated gradient background similar to the Solar Weather Application in xCode

Even though I have asked this question before, I would like to reach out again to clarify what I would like to accomplish with your help. I was wondering how you would create a background of and iOS application in xCode similar to the background of the Solar weather app (screenshots provided) that changes slightly over time (in a cycle). As you can see the gradient is very smooth and obviously contains more than two main points. Any help with example or snippets of code would be greatly appreciated. Thanks Again, Ben.

Screenshot 1Screenshot 2

like image 372
Ben Leather Avatar asked Feb 17 '13 11:02

Ben Leather


2 Answers

What I need is:

  1. adding a CAGradientLayer to your view controller (or custom view), e.g.:

    @property (nonatomic, retain) CAGradientLayer *gradient;
    
  2. In your view controller, in viewDidLoad, create and add the gradient layer to your view:

    self.gradient = [CAGradientLayer layer];
    gradient.frame = self.view.bounds;
    gradient.colors = [NSArray arrayWithObjects:
                   (id)topColor.CGColor,
                   (id)bottomColor.CGColor,
                   nil];
    gradient.locations = [NSArray arrayWithObjects:
                      [NSNumber numberWithFloat:0.0f],
                      [NSNumber numberWithFloat:0.7],
                      nil];
    [self.view.layer addSublayer:self.gradient];
    

    3a. add an NSTimer to your controller that will update self.gradient at proper intervals by doing:

      topColor = ...; bottomColor = ...;
      NSArray* newColors = [NSArray arrayWithObjects:
                     (id)topColor.CGColor,
                     (id)bottomColor.CGColor,
                     nil];
     [(CAGradientLayer *)self.layer setColors:newColors];
    

    This will allow you to exactly decide which colour you want to use for the gradient at each step. Otherwise, you might try with an animation, like this:

    3b. add the animation like this,

    - (void)animateLayer... {
    
      [UIView animateWithDuration:duration 
                            delay:0
                          options:UIViewAnimationOptionCurveEaseInOut
                       animations:^{
        [CATransaction begin];
        [CATransaction setAnimationDuration:duration];
    
          topColor = ...; bottomColor = ...;
          NSArray* newColors = [NSArray arrayWithObjects:
                     (id)topColor.CGColor,
                     (id)bottomColor.CGColor,
                     nil];
         [(CAGradientLayer *)self.layer setColors:newColors];
    
         [CATransaction commit];
      }
              completion:^(BOOL b) {
                  [self animateLayer..];
              }];
    }
    

You might also combine 3a and 3b.

like image 100
sergio Avatar answered Sep 20 '22 17:09

sergio


Simple working example:

.h file

@property (strong, nonatomic) CAGradientLayer *gradient;

.m file

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear: animated];

    self.gradient = [CAGradientLayer layer];
    self.gradient.frame = self.view.bounds;
    self.gradient.colors = @[(id)[UIColor purpleColor].CGColor,
                             (id)[UIColor redColor].CGColor];

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

    [self animateLayer];
}

-(void)animateLayer
{

    NSArray *fromColors = self.gradient.colors;
    NSArray *toColors = @[(id)[UIColor redColor].CGColor,
                          (id)[UIColor orangeColor].CGColor];

    [self.gradient setColors:toColors];

    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"colors"];

    animation.fromValue             = fromColors;
    animation.toValue               = toColors;
    animation.duration              = 3.00;
    animation.removedOnCompletion   = YES;
    animation.fillMode              = kCAFillModeForwards;
    animation.timingFunction        = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    animation.delegate              = self;

    // Add the animation to our layer

    [self.gradient addAnimation:animation forKey:@"animateGradient"];
}

You might want to implement an additional method to shift the colors, and then reanimate the changes. But this should help you get there.

like image 43
nmdias Avatar answered Sep 17 '22 17:09

nmdias