2009-04-15 2 views
0

Я создаю простой выбор цвета, управляемый пользовательским элементом управления ползунком.Как вы оптимизируете UIColor на iPhone?

Я передаю значение float из своего ползунка в метод конструктора UIColor и обновляю цвет фона CALayer при изменении значения.

Он работает очень плавно в симуляторе, но при работе на устройстве я получаю много мерцания.

Это только потому, что это связано с налогообложением GPU? Странно, когда вы двигаетесь через синий цвет. И изменение альфа-значения и яркости мерцает больше, чем изменение насыщенности и оттенка.

Должен ли я не передавать произвольные значения float при изменении значения ползунка? Если нет, как я могу ограничить это до меньших цветов для оптимизации?

Я думал об отключении неявных анимаций для свойства backgroundColor CALayer, но я не уверен, как это сделать.

Есть ли какие-либо трюки для оптимизации изменений UIColor.

Update

Я не использую DrawRect: или drawInRect:

Я просто изменить свойство BackgroundColor в виде CALayer. Каждый раз, когда touchsMoved: называется «Я захватил место», создаю значение с плавающей точкой от 0.0 до 1.0 и передаю сообщение моему делегату о том, что значение изменилось и вызывается метод (void) updateCurrentColor.

Вот пример моей реализации:

@implementation MyCustomSliderView 


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { 

    hueLocation = [[touches anyObject] locationInView:self]; 

    //Smoothing 
    if ((hueLocation.x > previousHueLocation.x) && ((hueLocation.x - previousHueLocation.x) > 1.0) && (hueLocation.x - previousHueLocation.x) < 10.0) { 
     hueLocation.x = previousHueLocation.x + 1.0; 
    } 

    if ((hueLocation.x < previousHueLocation.x) && ((previousHueLocation.x - hueLocation.x) > 1.0) && (previousHueLocation.x - hueLocation.x) < 10.0) { 
     hueLocation.x = previousHueLocation.x - 1.0; 
    } 

    //Percentage of screen. 
    hueValue = hueLocation.x/self.bounds.size.width; 

    //Clip to 1.0 & 0.0 
    if (hueValue > 1.0) { 
     hueValue = 1.0; 
    } 
    if (hueValue < 0.0) { 
     hueValue = 0.0; 
    } 

    NSLog(@"Value is: %f", hueValue); 
    NSLog(@"Location %f", hueLocation.x); 

    previousHueLocation = hueLocation; 

    if([delegate respondsToSelector:@selector(updateCurrentColor)]) { 
     [delegate updateCurrentColor]; 
    } 

} 


@implementation MyViewController 

- (void)updateCurrentColor { 

    currentColor = [UIColor colorWithHue:hueSliderView.hueValue 
           saturation:saturationSliderView.saturationValue 
           brightness:brightnessSliderView.brightnessValue 
            alpha:alphaSliderView.alphaValue]; 

    colorLayer.backgroundColor = currentColor.CGColor; 

} 

Сначала я подумал, что это прыгал значение из-за неточности сенсорного интерфейса. Функция сглаживания помогла, но она все еще мерцает, особенно с альфа-значением, даже когда мое местоположение изменяется только на 1 пиксель. Должен ли я ограничивать это ограниченным количеством цветов/значений вместо простого прохождения в произвольном поплавке? Опять же, отлично работает в симуляторе, кажется, просто проблема с производительностью.

+0

Опишите эффект, который вы получаете. Есть ли видимые вертикальные/горизонтальные «бары», где изменение видимо? Временно ли исчезают элементы? Получаете ли вы видимый, но нежелательный цвет перехода? – Artelius

+0

Нет баров. Цвет мерцает светлым и темным при изменении значений (оттенок, насыщенность, яркость, альфа). Если я иду очень медленно, это лучше, но все же иногда мерцает. Я скорректировал метод touchesMoved, чтобы перемещать только один пиксель за раз, не двигаясь выше 15. Это помогло. Тем не менее мерцает. –

ответ

2

Отключение неявных анимаций устраняет мерцание.

Я обновил изменения цветов методов так, чтобы цвет фона может быть оживлен при вызове из touchesBegan :, но не неявно анимированные при вызове из touchesMoved:

- (void)updateCurrentColorAnimated:(BOOL)animated { 

    currentColor = [UIColor colorWithHue:hueSliderView.hueValue 
           saturation:colorView.saturationValue 
           brightness:colorView.brightnessValue 
            alpha:alphaSlider.alphaValue]; 
    if (animated) { 

     colorLayer.backgroundColor = currentColor.CGColor; 

    } 

    if (!animated) { 

     [CATransaction begin]; 

     [CATransaction setValue:(id)kCFBooleanTrue 
         forKey:kCATransactionDisableActions]; 


     colorLayer.backgroundColor = currentColor.CGColor; 

     [CATransaction commit]; 

    } 

} 

Причины я свернул свой собственный слайдер так что я могу перейти к новым значениям вместо того, чтобы прекрасно поймать маленький слайдер, взаимодействие которого я нашел не очень хорошим.

1

Рисунок на iPhone двойной буферизации. Если вы мерцаете, это потому, что вы рисуете одну вещь, а затем другую - это не из-за проблем с скоростью.

Я думаю, вы делаете одну из следующих ошибок:

  • Обновления значения цвета и рисунок вашего цветного квадрата из синхронизации (так что цвет правильно не установлен, когда вы drawInRect :)
  • в противном случае для инициализации/рассчитать свой цвет правильно (так вы показываете недопустимые цвета)
  • Стирание или перерисовки прямоугольник, когда вы не должны

Другое дело, check ... colors в Cocoa - это плавающие значения от нуля до 1. Установка целочисленных значений от 0 до 255 (как используется в Интернете или Windows) приведет к серьезным проблемам. Если ваши цветовые вычисления превышают 0 до 255, то перед установкой UIColor разделите его на 255,0.

+0

Что означает «двойной буфер» в этом контексте? – erikprice

+0

@Matt Gallagher, спасибо, только что обновленный вопрос с моей реализацией. –

+0

@erikprice "double buffered" означает, что весь рисунок происходит за кадром, а затем копируется на экран после завершения рисования. Это означает, что стирание до белого цвета, за которым следует краска, не вызывает мерцания экрана, поскольку белое состояние никогда не отображается. –

Смежные вопросы