iOS:在自定义属性动画期间以正确的分辨率将CGImage绘制到CALayer的子类中

时间:2011-10-27 01:15:23

标签: ios animation calayer cgimage retina-display

我的智慧已经结束......

我有一个视图,它应该显示一个预先渲染的动画圆形部分,可用作png文件(视网膜和非视网膜版本,正确命名; pie_p_000.png与pie_p_000@2x.png相比)。应根据应用程序中某个百分比值的更改来动画此部分。所以我创建了一个UIView的子类,它的层次结构中有一个自定义的CALayer。计划是为CALayer子类实现自定义动画属性,并在重写方法drawInContext:中更改图片。到目前为止一切顺利,计划工作,当我使用视图的函数setPercentageWithFloat:更改百分比值时显示动画(下面的完整源代码)。 问题是:我真的不知道为什么我的iPhone4总是呈现低分辨率图像。我已经尝试过使用比例因子,但这并没有帮助。要么以正确的尺寸和低分辨率显示图像,要么将图像显示为双倍尺寸。 覆盖显示:直接设置内容属性会导致动画不显示(动画期间不显示图像);在动画时间之后,呈现最终图像。在这种情况下,会显示正确的分辨率图像。

顺便说一下:以下代码在错误处理,灵活性和优雅方面不是很复杂,因为它只是为了让这个东西运行;) - 所以图像仍然呈现翻转等等......

我希望有人对我有所暗示。 感谢

观点:

#import "ScrollBarView.h"
#import "ScrollBarLayer.h"

@implementation ScrollBarView

@synthesize sbl;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code 
    }
    return self;
}

- (void)setImagesWithName:(NSString*)imageName {
    ScrollBarLayer *ssbl = [[ScrollBarLayer alloc] init];
    ssbl.frame = CGRectMake(0, 0, 30, 30);
    [ssbl setImagesWithName:imageName];
    [self.layer addSublayer:ssbl];

    self.sbl = ssbl;

    [ssbl release];
}

- (void) dealloc {
    self.sbl = nil;
    [super dealloc];
}

- (void)setPercentageWithFloat:(CGFloat)perc {
    if(perc > 1.0){
        perc = 1.0;
    } else if(perc < 0) {
        perc = 0;
    }

    [self.sbl setPercentage:perc];

    CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"percentage"];
    ba.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    ba.duration = 0.8;
    ba.toValue = [NSNumber numberWithFloat:perc];
    [self.sbl addAnimation:ba forKey:nil];
}
@end

View可以配置为使用不同的名称(theName)使用不同的图像(使用函数setImagesWithName :)。在此方法中,View将ScrollBarLayer添加到其图层属性。

图层:

#import "ScrollBarLayer.h"

@implementation ScrollBarLayer

@synthesize filename;
@dynamic percentage;

- (id)init {
    self = [super init];
    if (self) {

    }
    return self;
}

- (void)setImagesWithName:(NSString*)imageName {
    self.frame = CGRectMake(0, 0, 30, 30);
    self.percentage = 0;
    self.filename = imageName;
}

+ (BOOL) needsDisplayForKey:(NSString*)key {
    if([key isEqualToString:@"percentage"]) {
        return YES;
    }
    return [super needsDisplayForKey:key];
}

- (void) drawInContext:(CGContextRef)ctx {

    int imageIdx = (int)roundf((float)199 * self.percentage);
    NSString *thisfilename = [self.filename stringByAppendingString:[NSString stringWithFormat:@"%03d.png", i+1]];
    UIImage* c = [UIImage imageNamed:thisfilename];
    CGImageRef img = [c CGImage];
    CGSize sz = CGSizeMake(CGImageGetWidth(img), CGImageGetHeight(img));

    UIGraphicsBeginImageContextWithOptions(CGSizeMake(sz.width, sz.height), NO, 0.0);
    CGContextDrawImage(ctx, CGRectMake(0, 0, sz.width, sz.height), img);
    UIGraphicsEndImageContext();
}

- (void) dealloc {
    self.pictures = nil;
    self.filename = nil;
    [super dealloc];
}

@end

1 个答案:

答案 0 :(得分:0)

我也需要对此有所了解。

我认为问题出在点和像素之间......我认为你应该检查设备是否有视网膜显示器,如果是,你应该替换CGContextDrawImage(...)CGRect(在第二个参数中)对于一半宽度和高度的人。

#define IS_RETINA_DISPLAY() ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00)

...
UIGraphicsBeginImageContextWithOptions(CGSizeMake(sz.width, sz.height), NO, 0.0);

if (IS_RETINA_DISPLAY())
{
    CGContextDrawImage(ctx, CGRectMake(0, 0, sz.width/2.0f, sz.height/2.0f), img);
} else
{
    CGContextDrawImage(ctx, CGRectMake(0, 0, sz.width, sz.height), img);
}
UIGraphicsEndImageContext();
...

但我不确定这种鳃会给你一个“顺利”的结果......

相关问题