Succéssion de flash .

CeetixCeetix Membre
23:22 modifié dans API UIKit #1
Salut tout le monde !

Voilà , j'essaie de faire une petite application qui fera flasher l'écran de l'iphone.
Pour se faire j'ai créé ne View où je mets un bouton "flash" qui déclanchera une succession de flash quand j'appuierai dessus.
J'ai ensuite créé une autre view(appelée "page") que je place par dessus mon écran (donc première view et bouton), que je met en blanc et dont le alpha est à  0.00 .
J'ai essayé plusieurs fois de créer ce flash mais je n'arrive jamais à  faire succéder deux animation à  la suite.

Exemple de code :

<br />- (IBAction)flash {<br />&nbsp; &nbsp;  [UIView beginAnimations:nil context:NULL];<br />&nbsp; &nbsp;  [UIView setAnimationDuration:0.2];<br />&nbsp; &nbsp;  page.alpha = 1.00;<br />&nbsp; &nbsp;  [UIView commitAnimations];<br /><br />&nbsp; &nbsp;  [UIView beginAnimations:nil context:NULL];<br />&nbsp; &nbsp;  [UIView setAnimationDuration:0.2];<br />&nbsp; &nbsp;  mapage.alpha = 0.00;<br />&nbsp; &nbsp;  [UIView commitAnimations]<br />&nbsp; &nbsp;  }<br /><br />


Déjà  il ne fait pas le deux animations mais juste la derniere. Quand je clique sur flash il me met directement du blanc et ensuite fait en 0,2 seconde le alpha 1.00 to 0.00.

Comment faire ? :(

Réponses

  • Philippe49Philippe49 Membre
    23:22 modifié #2
    dans 1225816644:

    Comment faire ? :(


    Tu regardes deux topics avant  :) :)
  • CeetixCeetix Membre
    23:22 modifié #3
    ::) Oui j'ai regardé mais je vois pas tres bien comment faire .
  • Philippe49Philippe49 Membre
    23:22 modifié #4
    [UIView setAnimationDelegate:aDelegate];

    [UIView setAnimationDidStopSelector:@selector(la methode qui reçoit )];

    La méthode qui reçoit doit avoir trois arguments (voir la doc de UIView et les exemples de renvoi)



  • CeetixCeetix Membre
    23:22 modifié #5
    Ok! Merci ^^
  • MalaMala Membre, Modérateur
    23:22 modifié #6
    Histoire d'apporter de l'eau au moulin, je ne vais pas répondre à  la question (Phil y a déjà  répondu) mais au pourquoi ça marche pas quand on enquille deux animations l'une derrière l'autre.

    En fait, il faut bien comprendre que Core Animation (on va dire CA pour faire plus court), qu'on soit sur Mac ou iPhone, est multithreadé (il fonctionne en parallèle de l'application). Lorsqu'on passe dans un méthode et qu'on appelle une fonctionnalité de CA, une transaction implicite est créée. Toutes les actions réalisées dans la méthode ne seront effectuées qu'après la fin de la méthode. Donc dans ton cas la première animation ne va pas être prise en compte puisque CA ne voit que les modifications de la deuxième.

    Comment faire alors? Et bien on utiliser des transactions explicite de la forme:
    <br />[CATransaction begin];<br />[CATransaction setValue:[NSNumber numberWithFloat:1] forKey:kCATransactionAnimationDuration];<br />// Pour l&#39;exemple, j&#39;ajoute un layer à  mon layer principal<br />[mainLayer addSublayer:secondLayer];<br />[CATransaction commit];<br /><br />[CATransaction begin];<br />[CATransaction setValue:[NSNumber numberWithFloat:1] forKey:kCATransactionAnimationDuration];<br />// Et la je supprime mon layer affiché<br />[secondLayer removeFromSuperlayer];<br />[CATransaction commit];<br />
    


    Mais cela ne suffit pas. Dans cet exemple, les deux animations vont s'exécuter mais la seconde va très (trop) vite remplacée la première. CA n'aura sans doute même pas le temps de prendre en compte la première. Il nous faut donc d'une part forcer la prise en compte et d'autre part attendre un peu pour qu'elle est le temps de s'exécuter. On fera  donc plutôt quelque chose comme ça:

    <br />[CATransaction begin];<br />[CATransaction setValue:[NSNumber numberWithFloat:1] forKey:kCATransactionAnimationDuration];<br />[mainLayer addSublayer:secondLayer];<br />[CATransaction commit];<br /><br />// On force la prise en compte des modifications<br />[CATransaction flush];<br /><br />// On fait patienter le thread principal<br />[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];<br /><br />[CATransaction begin];<br />[CATransaction setValue:[NSNumber numberWithFloat:1] forKey:kCATransactionAnimationDuration];<br />[secondLayer removeFromSuperlayer];<br />[CATransaction commit];<br /><br />// On force la prise en compte des modifications<br />[CATransaction flush];<br />
    


    Cet usage est par contre plus contraignant que la méthode donnée par Philippe car comme on bloque le thread principal (ce qui n'est pas le cas avec un delegate) on empêche toute action de l'utilisateur pendant ce temps. Mais d'un autre côté cela peu être un avantage dans certains cas où on veux justement modifier l'interface sans que l'utilisateur puisse intervenir pendant ce temps sur d'autres layers.

    L'utilisation des transactions explicites est aussi très pratique lorsqu'on veut par exemple bouger un layer à  la souris. On peut alors cout-circuiter directement le temps d'animation de la manière suivante:
    <br />[CATransaction begin];<br />[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];<br /><br />//<br />// Ici on vient modifier la position d&#39;un layer par rapport au coordonnées souris lors <br />// d&#39;un drag où à  un redimensionnement de la fenêtre (OS X uniquement ;) ).<br />//<br /><br />[CATransaction commit];<br />
    


    Après pour des choses plus élaborées, on va effectivement se recentrer vers les animations.

  • Philippe49Philippe49 Membre
    23:22 modifié #7
    dans 1225883422:

    Cet usage est par contre plus contraignant que la méthode donnée par Philippe car comme on bloque le thread principal (ce qui n'est pas le cas avec un delegate) on empêche toute action de l'utilisateur pendant ce temps. Mais d'un autre côté cela peu être un avantage dans certains cas où on veux justement modifier l'interface sans que l'utilisateur puisse intervenir pendant ce temps sur d'autres layers.


    J'avais aussi essayé avec un NSTimer pour lancer la seconde animation (ou en jouant sur la property delay), mais le problème est que la durée réelle du thread de l'animation (duration) est très imprécise par rapport à  celle demandée.
  • AliGatorAliGator Membre, Modérateur
    23:22 modifié #8
    Y'a un truc que je comprend pas sur le principe, d'après ce que dit la doc.
    En pratique je remarque aussi qu'on ne peut pas commiter 2 animations à  la suite (enfin si on peut mais on ne verra que la dernière), mais quand je lis la doc :
    setAnimationBeginsFromCurrentState:
    Sets whether the animation should begin playing from the current state.

    + (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState

    Parameters
    fromCurrentState
    YES if animations should begin from their currently visible state; otherwise, NO.

    Discussion
    If set to YES when an animation is in flight, the current view position of the in-flight animation is used as the starting state for the new animation. If set to NO, the in-flight animation ends before the new animation begins using the last view position as the starting state. This method does nothing if an animation is not in flight or invoked outside of an animation block. Use the beginAnimations:context: class method to start and the commitAnimations class method to end an animation block. The default value is NO.
    Ainsi que
    commitAnimations
    Ends an animation block and starts animations when this is the outer animation block.

    + (void)commitAnimations

    Discussion
    If the current animation block is the outer animation block, starts animations when the application returns to the run loop. Animations are run in a separate thread so the application is not blocked. In this way, multiple animations can be piled on top of one another. See setAnimationBeginsFromCurrentState: for how to start animations while others are in progress.
    En lisant ces deux choses là , ça me laisse penser que d'une part la première méthode permet d'empiler plusieurs animations et que si on laisse à  NO elle vont s'enchaà®ner, attendant que la première ait fini pour lancer la 2e (alors qu'en pratique ce n'est pas le cas)... Mais aussi qu'on peut "empiler les animations les unes au dessus des autres" comme ils disent, et qu'on peut imbriquer les blocs d'animations, genre
    [UIView beginAnimations:@&quot;Outerblock&quot; context:NULL];<br />&nbsp;  [UIView beginAnimations:@&quot;firstAnim&quot; context:NULL];<br />&nbsp;  // ...<br />&nbsp;  [UIView commitAnimations]; // fin firstAnim<br /><br />&nbsp;  [UIView beginAnimations:@&quot;secondAnim&quot; context:NULL];<br />&nbsp;  // ...<br />&nbsp;  [UIView commitAnimations]; // fin secondAnim<br />[UIView commitAnimations]; // fin OuterBlock
    
    Mais ça n'a pas l'air de marcher mieux...

    Alors, doc mal foutue, laissant croire qu'on peut empiler et enchaà®ner les animations aussi simplement (plutôt que d'attendre la delegate method pour lancer la suivante) ? ou astuce de sioux qu'on a pas vue qui permettrait de faire marcher ça comme le laisse entendre la doc ? Ou mauvaise traduction de la doc de ma part ?  ???
  • Philippe49Philippe49 Membre
    novembre 2008 modifié #9
    Oui la lecture de cette page de la doc est curieuse, je pensais aussi y avoir trouvé une réponse.
    En fait un essai

    [UIView beginAnimations:@toto context:NULL];
    [UIView setAnimationDuration:2.];
    myView.center=CGPointMake(myView.center.x+10.,myView.center.y+10.);
    [UIView beginAnimations:@titi context:NULL];
    [UIView setAnimationDuration:2.];
    myView.layer.opacity/=2.;
    [UIView commitAnimations];
    [UIView commitAnimations];


    réalise les deux animations en simultané
  • Philippe49Philippe49 Membre
    23:22 modifié #10
    Et si on agit deux fois sur la property center, cela se fait avec un mini-décalage qui se voit avec un sursaut de la vue, et le cumul des transformations

    [UIView beginAnimations:@toto context:NULL];
    [UIView setAnimationDuration:2.];
    myView.center=CGPointMake(myView.center.x+10.,myView.center.y+10.);
    [UIView beginAnimations:@titi context:NULL];
    [UIView setAnimationDuration:2.];
    myView.center=CGPointMake(myView.center.x+10.,myView.center.y+10.);
    [UIView commitAnimations];
    [UIView commitAnimations];


  • AliGatorAliGator Membre, Modérateur
    23:22 modifié #11
    Tout à  fait, c'est ce que j'avais remarqué aussi.
    Du coup pour moi la doc nous ment, elle nous fait croire qu'on peut cumuler des animations de façon séquentielle avec ce mécanisme, alors que c'est même pas vrai, la vilaine !
  • CeetixCeetix Membre
    23:22 modifié #12
    Merci pour toutes ces explications les mecs ! C'est déjà  un peu plus clair dans ma tête :)
  • fouffouf Membre
    23:22 modifié #13
    Peut-être que ce n'est valable que pour des animations sur des properties différentes ?
  • Philippe49Philippe49 Membre
    23:22 modifié #14
    @fouf : C'est marrant parce que tous, on passe par les mêmes étapes ...
    Non, le premier exemple essayé est sur des properties différentes , par contre c'est la même view, donc le même layer. Essayons avec des vues différentes :

    [size=12pt]essai n°3[/size]
    [UIView beginAnimations:@toto context:NULL];
    [UIView setAnimationDuration:2.];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationWillStartSelector:@selector(animationWillStart:context:)];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
    myView.center=CGPointMake(myView.center.x+10., myView.center.y+10.);
    [UIView beginAnimations:@titi context:NULL];
    [UIView setAnimationDuration:5.];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationWillStartSelector:@selector(animationWillStart:context:)];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
    button.center=CGPointMake(myView.center.x+10., myView.center.y+10.);
    //lineView.layer.opacity/=2.;
    [UIView commitAnimations];
    [UIView commitAnimations];
    }
    -(void) animationWillStart:(NSString*)animId context:(void*)context {
    NSLog(@start);
    }

    -(void) animationDidStop:(NSString*)animId finished:(BOOL) flag context:(void*)context {
    NSLog(@stop);
    }

    [size=12pt]Résultat :[/size]
    [Session started at 2008-11-05 20:38:12 +0100.]
    2008-11-05 20:38:16.530 MovingAndSubviews[4765:20b] start
    2008-11-05 20:38:16.531 MovingAndSubviews[4765:20b] start
    2008-11-05 20:38:18.528 MovingAndSubviews[4765:20b] stop
    2008-11-05 20:38:21.528 MovingAndSubviews[4765:20b] stop

    Même date de départ ...
Connectez-vous ou Inscrivez-vous pour répondre.