2009-04-15 5 views
0

Je crée un sélecteur de couleur simple contrôlé par un contrôle de type curseur personnalisé.Comment optimiser UIColor sur l'iPhone?

Je transmets une valeur flottante de mon curseur à une méthode de constructeur UIColor et je mets à jour la couleur d'arrière-plan d'un CALayer lorsque la valeur change.

Il fonctionne très bien dans le simulateur, mais je me mets à scintiller lorsque je cours sur l'appareil. Est-ce juste parce qu'il est trop taxer le GPU? C'est étrangement le pire quand on passe au bleu. Et changer la valeur alpha et la luminosité scintillent plus que changer la saturation et la teinte.

Ne dois-je pas transmettre des valeurs flottantes arbitraires lorsque la valeur du curseur change? Si non, comment pourrais-je contraindre cela à moins de couleurs pour l'optimisation?

J'ai pensé à désactiver les animations implicites pour la propriété backgroundColor du CALayer, mais je ne suis pas sûr de savoir comment faire cela.

Y a-t-il des astuces pour optimiser les changements UIColor?

Mise à jour

Je ne suis pas en utilisant drawRect: ou drawInRect:

Je suis juste changer la propriété backgroundColor d'un CALayer. Chaque fois que touchesMoved: est appelée, j'attrape l'emplacement, crée une valeur flottante de 0.0 à 1.0 et envoie un message à mon délégué indiquant que la valeur a changé et appelle la méthode - (void) updateCurrentColor.

Voici un exemple de ma mise en œuvre:

@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; 

} 

Au début, je pensais qu'il était sauter des valeurs en raison de l'imprécision de l'interface tactile. La fonction de lissage a aidé, mais elle scintille encore, surtout avec la valeur alpha, même si ma position ne change que de 1 pixel. Dois-je limiter cela à une quantité limitée de couleurs/valeurs au lieu de simplement passer dans un flotteur arbitraire? Encore une fois, fonctionne très bien dans le simulateur, semble être juste un problème de performance.

+0

Décrivez l'effet que vous obtenez. Existe-t-il des «barres» verticales/horizontales visibles où le changement est visible? Est-ce que les éléments disparaissent temporairement? Avez-vous une couleur de transition visible mais non désirée? – Artelius

+0

Aucune barre. La couleur scintille de façon claire et sombre lorsque je change les valeurs (teinte, saturation, luminosité, alpha). Si je vais très lentement, c'est mieux, mais ça scintille parfois. J'ai ajusté la méthode touchesMouvées pour déplacer seulement un pixel à la fois à moins de passer au-dessus de 15. Cela m'a aidé. Toujours clignote cependant. –

Répondre

2

La désactivation des animations implicites a éliminé le scintillement.

J'ai mis à jour la couleur changeante des méthodes afin que la couleur de fond peut être animé lorsqu'il est appelé à partir touchesBegan :, mais pas implicitement animé lorsqu'il est appelé à partir 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]; 

    } 

} 

La raison pour laquelle je roulais mon propre curseur est pour que je puisse sauter à de nouvelles valeurs au lieu d'avoir à saisir parfaitement le petit contrôle du curseur, dont l'interaction n'a pas été très bonne.

1

Le dessin sur l'iPhone est à double tampon. Si vous obtenez des scintillements, c'est parce que vous dessinez une chose et puis une autre - ce n'est pas à cause de problèmes de vitesse.

Je suppose que vous faites l'une des erreurs suivantes:

  • Mise à jour de votre valeur de couleur et le dessin de votre carré de couleur de synchronisation (de sorte que la couleur n'est pas réglé correctement lorsque vous drawInRect :)
  • A défaut d'initialiser/calculer votre couleur correctement (si vous affichez des couleurs invalides)
  • Erasing ou redessiner votre rectangle lorsque vous ne devriez pas

Une autre chose à check ... les couleurs dans Cocoa sont flottantes de zéro à 1. La définition de valeurs entières de 0 à 255 (comme sur le web ou Windows) entraînera des problèmes très sérieux. Si vos calculs de couleurs sont compris entre 0 et 255, divisez par 255,0 avant de définir l'UIColor.

+0

Que signifie "double buffered" dans ce contexte? – erikprice

+0

@Matt Gallagher, merci, juste une question mise à jour avec ma mise en œuvre. –

+0

@erikprice "double buffered" signifie que tout dessin se passe hors écran puis est copié à l'écran une fois le dessin terminé. Cela signifie qu'un effacement au blanc, suivi d'une peinture noire, ne provoque aucun scintillement à l'écran puisque l'état blanc n'est jamais affiché. –