在iOS上,如果一个视图有多个图层,drawRect可以只选择一个要显示的图层吗?

时间:2012-05-27 06:49:09

标签: iphone ios uiview calayer drawrect

在iOS上,如果一个视图有多个图层,那么drawRect方法可以选择任何一个图层来显示,1秒后选择另一个图层来显示,以实现动画效果吗?

现在,我有几个图层,但我不认为它们是视图的图层(它们只是不是父图层子图层的单个图层),因为我只是使用

创建它们
CGLayerCreateWithContext(context, self.view.bounds.size, NULL);

drawRect中,我使用

CGContextDrawLayerAtPoint(context, self.bounds.origin, layer1);

将图层绘制到视图上...它可以工作,但这不是像在图层上绘制图层(在图层的图层上绘制图层)吗?是不是有更快的方法,即告诉视图使用layer1layer2,有点像

self.layer = layer1;  

但它不能,因为layer是只读的。这可以实现吗?

2 个答案:

答案 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