在iOS上,如果一个视图有多个图层,那么drawRect
方法可以选择任何一个图层来显示,1秒后选择另一个图层来显示,以实现动画效果吗?
现在,我有几个图层,但我不认为它们是视图的图层(它们只是不是父图层子图层的单个图层),因为我只是使用
创建它们CGLayerCreateWithContext(context, self.view.bounds.size, NULL);
在drawRect
中,我使用
CGContextDrawLayerAtPoint(context, self.bounds.origin, layer1);
将图层绘制到视图上...它可以工作,但这不是像在图层上绘制图层(在图层的图层上绘制图层)吗?是不是有更快的方法,即告诉视图使用layer1
或layer2
,有点像
self.layer = layer1;
但它不能,因为layer
是只读的。这可以实现吗?
答案 0 :(得分:3)
您正尝试使用CALayer
绘图方法绘制CGLayer
个对象。这些是不同的东西,不会互换。但是,如果我正确理解了您的问题,那么在一段时间后您根本不需要使用drawRect:
来切换图层。这是我的基本工作代码示例:
#import <QuartzCore/QuartzCore.h>
@interface TTView {
NSUInteger index;
NSArray *layers;
CALayer *currentLayer;
}
@end
@implementation TTView
- (void)switchView {
// Remove the currently visible layer
[currentLayer removeFromSuperlayer];
// Add in the next layer
currentLayer = [layers objectAtIndex:index];
[self.layer addSublayer:currentLayer];
// Increment the index for next time
index += 1;
if (index > [layers count] - 1) {
// If we have reached the end of the array, go back to the start. You can exit the loop here by calling a different method followed by return;
index = 0;
}
// Call this method again after 1 second
[self performSelector:@selector(switchView) withObject:nil afterDelay:1];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
// Basic initialisation. Move this to whatever method your view inits with.
self = [super initWithCoder:aDecoder];
if (self) {
// Create some random objects with layers to display. Place your layers into the array here.
UIView *a = [[UIView alloc] initWithFrame:self.bounds];
a.backgroundColor = [UIColor redColor];
UIView *b = [[UIView alloc] initWithFrame:self.bounds];
b.backgroundColor = [UIColor greenColor];
UIView *c = [[UIView alloc] initWithFrame:self.bounds];
c.backgroundColor = [UIColor blueColor];
// Add the layers to the array.
layers = [[NSArray alloc] initWithObjects:a.layer, b.layer, c.layer, nil];
// Call the method to start the loop.
[self switchView];
}
return self;
}
显然,您应该用您计划以这种方式设置动画的任何图层替换我的3个普通彩色视图,并可能整理实例变量。这只是一个基本的代码示例,可以满足您的需求。
答案 1 :(得分:3)
按照@ PartiallyFinite的示例,通过将视图的图层的contents
属性设置为您选择的CGImage
,可以获得相同类型的效果。
这比覆盖-drawRect:
和绘制更有效,因为它避免了额外的绘制操作并上传到视频硬件。
#import <QuartzCore/QuartzCore.h>
@interface TTView {
NSUInteger index;
NSMutableArray *images;
}
@end
@implementation TTView
- (id)initWithCoder:(NSCoder *)aDecoder {
// Basic initialisation. Move this to whatever method your view inits with.
self = [super initWithCoder:aDecoder];
if (self) {
// Create some random images to display. Place your images into the array here.
CGSize imageSize = self.bounds.size;
images = [[NSMutableArray alloc] init];
[images addObject:[self imageWithSize:imageSize color:[UIColor redColor]]];
[images addObject:[self imageWithSize:imageSize color:[UIColor greenColor]]];
[images addObject:[self imageWithSize:imageSize color:[UIColor blueColor]]];
[self switchView];
}
return self;
}
- (UIImage*)imageWithSize:(CGSize)imageSize color:(UIColor*)color {
UIGraphicsBeginImageContext(imageSize);
// Draw whatever you like here.
// As an example, we just fill the whole image with the color.
[color set];
UIRectFill(CGRectMake(0, 0, imageSize.width, imageSize.height));
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
- (void)switchView {
UIImage* image = [images objectAtIndex:index];
self.layer.contents = (id)(image.CGImage);
index = (index + 1) % images.count;
[self performSelector:@selector(switchView) withObject:nil afterDelay:1];
}
// DO NOT override -drawRect:, and DO NOT call -setNeedsDisplay.
// You're already providing the view's contents.
@end