Moduspwnens
Moduspwnens

Reputation: 525

CALayer autoresizing on iPhone/iPad: How?

I'm trying to create a UIView subclass ("GradientView") that will fill itself with a gradient of various colors. I've implemented it by adding a CAGradientLayer as a sub-layer of UIView's layer.

It looked good, but when the screen was rotated, it didn't resize the gradient layer. Having no luck finding a BOOL property on the layer to toggle, I overrode layoutSubviews in the GradientView.

-(void)layoutSubviews {
    self.gradientLayer.frame = self.bounds;
}

This works, but the stuff behind the GradientView is still visible during the device rotation animation. What is the easiest way to 'autoresize' that CAGradientLayer to match its parent layer's bounds so that the animation is smooth (like for UIView autoresizing)?

Upvotes: 21

Views: 15435

Answers (5)

Onnmir
Onnmir

Reputation: 1030

in my case this work:

[[[view.layer sublayers] objectAtIndex:gradientIndex] setFrame:view.bounds];

Upvotes: 0

user1172004
user1172004

Reputation: 177

Note that returning CAGradientLayer as the layer class only works if you set the view background color to transparent. You'll need to set the layer background color if you need a color other than transparent.

Upvotes: 1

l8nite
l8nite

Reputation: 5172

You can probably get away with defining the +layerClass method on a custom UIView...

@implementation MyGradientView
+(Class) layerClass {
    return [CAGradientLayer class];
}
@end

You can initialize the layer in your controller's viewDidLoad() (or wherever), something like...

-(void)viewDidLoad {
    [super viewDidLoad];
    [(CAGradientLayer*)[mMyGradientViewInstance layer] setColors:nil];
}

Upvotes: 29

Brad
Brad

Reputation: 11505

I would:

  1. Increase the size of your view to the maximum of each dimension in the willRotateToInterfaceOrientation code. (For example for an 320x480 iPhone - set the dims to 480x480).

  2. Set the bounds in accordance to the newly-rotated view in the didRotateFromInterfaceOrientation function.

This should make it so that the view is large enough so that regardless of how it is oriented during animation, it will cover the entire screen. It won't be "smooth" - because the gradient will have to be rotated, but at least you will not see behind the layer in the middle of the rotation.

Upvotes: 4

Luke Mcneice
Luke Mcneice

Reputation: 2720

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {

    CGRect b;

    if(UIInterfaceOrientationIsLandscape(toInterfaceOrientation))b = CGRectMake(0, 0, 480, 320);
    else b = CGRectMake(0, 0, 320, 480);    

    [CATransaction begin];
    [CATransaction setValue:[NSNumber numberWithFloat:duration] forKey:kCATransactionAnimationDuration];
    [self.view.layer setBounds:b];
    [CATransaction commit];

}

Upvotes: 2

Related Questions