iOS: рисование CGImage в подклассе CALayer во время анимации пользовательских свойств в правильном разрешении - PullRequest
1 голос
/ 27 октября 2011

Я в конце моей мудрости ...

У меня есть представление, в котором должен отображаться анимированный круговой разрез, который предварительно отрисован и доступен в виде 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

Вид можно настроить для работы с разными изображениями (используя функцию setImagesWithName :), используя разные имена (theName). В этом методе представление добавляет 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 голосов
/ 23 февраля 2012

Мне бы тоже нужен был свет.

Я думаю, что проблема заключается в точках и пикселях ... Я думаю, что вы должны проверить, если устройство имеет дисплей сетчатки, и если так, вы должны заменить 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();
...

Но я не уверен, что этот жабр даст вам "гладкий" результат ...

...