CALayer委托UITableViewCell中的回调 - 工作流

时间:2011-09-29 00:12:03

标签: iphone uitableview delegates core-animation calayer

我正在使用几个CALayers在UITableViewCell子类中绘制我的内容。实际绘图应该通过调用CALayer委托方法drawLayer:inContext:来实现。 但委托方法永远不会被调用。

这是我的结构:

  • CustomCell:UITalbeViewCell
    • 创建CustomCellContentView:UIView
      • 创建CABackgroundLayer:CALayer
      • 创建CATextLayer:CALayer
    • 创建CALayerDelegate:NSObject

每个customCell都有一个customContentView,它包含所有用于绘图的CALayers。 每个customCell都会为要调用的CALayers创建一个caLayerDelegate。 caLayerDelegate向customCell报告。

CustomCell:

#define CALAYER_TEXTLAYER_NAME              @"CATextLayer"
#define CALAYER_BGLAYER_NAME                @"CABackgroundLayer"

...

- (id) customContentViewForCurrentCell
{
    CGRect contentViewFrame = CGRectMake(-CC_LEFTRIGHT_PADDING, 0., self.contentView.bounds.size.width, self.contentView.bounds.size.height);

    CustomCellContentView *cellContentView = [[[CustomCellContentView alloc] initWithFrame: contentViewFrame] autorelease];

    CALayerDelegate *layerDelegate = [[CALayerDelegate alloc] initWithView: self];
    cellContentView.layerDelegate = layerDelegate;
    [cellContentView setupSubLayers];

    [layerDelegate release];

    return cellContentView;
}

#pragma mark - Initialisation

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

    if (!self) 
        return nil;

    self.customContentView = (CustomCellContentView *)[self customContentViewForCurrentCell];
    self.customContentView.opaque = TRUE;

    self.backgroundColor = [UIColor clearColor];
    self.selectionStyle = UITableViewCellSelectionStyleNone;
    [self.contentView addSubview: self.customContentView];

    return self;
}

#pragma mark - Cell Update

- (void) refreshLayout
{
    [self setNeedsDisplay];
    [self.customContentView setNeedsDisplay];
}

...

#pragma mark - CALayer Delegate Methods

-(void) drawLayer: (CALayer*) layer inContext: (CGContextRef) context 
{

}

-(void) drawCABackgroundLayer: (CALayer*) layer inContext: (CGContextRef) context
{
    UIGraphicsPushContext(context);

    CGRect contentRect = [layer bounds];
    UIImage *bgImage = [[ImageCacheController sharedImageCache] imageFromCache: GENERIC_BGIMAGE_FILENAME];

    [bgImage drawInRect: CGRectMake(contentRect.origin.x, contentRect.origin.y, contentRect.size.width, contentRect.size.height)];

    UIGraphicsPopContext();
}

-(void) drawCATextLayer: (CALayer*) layer inContext: (CGContextRef) context
{
    UIGraphicsPushContext(context);

    CGContextSetShadowWithColor(context, CGSizeMake(0.f, 2.0f), 0.0f, [UIColor mainLabelShadowColor].CGColor);

    [[UIColor mainLabelColor] set];
    UIFont *mainFont = [UIFont fontWithName: FONT_INFOS size: CC_MAINLABEL_FONTSIZE_MAX];

    [@"ArthurDent" drawAtPoint: [self mainViewPosition] 
                           forWidth: CC_MAINLABEL_WIDTH 
                           withFont: mainFont 
                        minFontSize: CC_MAINLABEL_FONTSIZE_MAX 
                     actualFontSize: NULL 
                      lineBreakMode: UILineBreakModeTailTruncation 
                 baselineAdjustment: UIBaselineAdjustmentAlignBaselines];

    UIGraphicsPopContext();
}

CustomCellContentView:

@interface CustomCellContentView : UIView 
{
    CALayerDelegate *layerDelegate;

    CALayer *backgroundLayer;
    CALayer *textLayer;
}

@property (nonatomic, retain) CALayerDelegate *layerDelegate;

@property (nonatomic, retain) CALayer *backgroundLayer;
@property (nonatomic, retain) CALayer *textLayer;

- (void) setupSubLayers;

@end



@implementation CustomCellContentView

@synthesize textLayer, backgroundLayer, layerDelegate;

#pragma mark - Initialisation

- (id) initWithFrame:(CGRect)frame
{
    self = [super initWithFrame: frame];

    if(!self)
        return nil;

    return self;
}

- (void) setupSubLayers
{    
    self.textLayer = [CALayer layer];
    self.textLayer.name = CALAYER_TEXTLAYER_NAME;
    self.textLayer.shadowColor = [UIColor mainLabelShadowColor].CGColor;
    self.textLayer.shadowOffset = CGSizeMake(0.0f, 2.0f);
    self.textLayer.shadowOpacity = 1.f;
    self.textLayer.shadowRadius = 0.f;
    self.textLayer.needsDisplayOnBoundsChange = TRUE;
    self.textLayer.delegate = self.layerDelegate;

    self.backgroundLayer = [CALayer layer];
    self.backgroundLayer.name = CALAYER_BGLAYER_NAME;
    self.backgroundLayer.needsDisplayOnBoundsChange = TRUE;
    self.backgroundLayer.delegate = self.layerDelegate;

    [self.layer addSublayer: self.textLayer];
    [self.layer addSublayer: self.backgroundLayer];

    [self.textLayer setNeedsDisplay];
    [self.backgroundLayer setNeedsDisplay];
}

#pragma mark - SetNeedsDisplay Overwritten

- (void) setNeedsDisplay
{
    [super setNeedsDisplay];

    [self.layer setNeedsDisplay];    
    [self.textLayer setNeedsDisplay];
    [self.backgroundLayer setNeedsDisplay];
}

...

CALayerDelegate:

@implementation CALayerDelegate

#pragma mark - Initialisation

-(id) initWithView: (UIView *) view 
{
    self = [super init];

    if (!self) 
        return nil;

    _view = view;

    return self;
}

#pragma mark - CALayer Delegate Methods

-(void) drawLayer: (CALayer*) layer inContext: (CGContextRef) context 
{
    NSString* methodName = [NSString stringWithFormat: @"draw%@:inContext:", [layer name]];

    SEL selector = NSSelectorFromString(methodName);

    if (![_view respondsToSelector: selector])
        selector = @selector(drawLayer:inContext:);

    [_view performSelector: selector 
                withObject: layer 
                withObject: (id)context];
}

@end

我已经阅读过UIViewController,最好在awakeFromNib中创建子CALayers:而不是在initWithFrame:中,因为在initWithFrame:之后会出现某种形式的层 - 支持,这会丢弃子层的创建。那么,您应该只在加载视图后添加子图层?

我使用单独的CALayerDelegate - 对象,因此CustomCell及其视图仅负责customContentView.layer。

任何人都知道,我做错了什么?

提前致谢!!

2 个答案:

答案 0 :(得分:0)

来自描述'委托'属性的CALayer的documentation:'在iOS中,如果图层与UIView对象相关联,则必须将此属性设置为拥有图层的视图。

如果我正确阅读,那么您需要将CustomCellContentView设置为图层委托。将CALayerDelegate中的功能直接移动到您的自定义视图类中,看看是否有效。无论如何,这将是执行此操作的标准方法,而不是仅仅作为代理创建一个单独的类。

答案 1 :(得分:0)

检查您的框架是否不是CGRectZero。

我和你描述的问题有类似的问题。如果框架是CGRectZero,这将阻止调用drawLayer:inContext。