9
votes

Chaîne UIView Animations avec intervalles de temps

J'ai besoin d'animer 3 UIViews (FADE IN / OUT). 1 Durée d'animation est de 0,6 (cycle de fondu in / extérieur est de 0,6 + 0,6S). Mais je dois lancer des animations en 0.2 secondes.

  • 1ère animation doit être lancé en 0.0 secondes. LI>
  • 2e animation doit être lancé en 0.2 secondes. Li>
  • 3ème animation doit être lancé en 0,4 seconde. LI> ul>

    et tous devraient être en boucle "indéfiniment" (jusqu'à la gâchette). P>

    Qu'est-ce que j'ai pour le moment: P>

    [self performSelector:@selector(animateView:) withObject:thirdView afterDelay:0.6];
    


8 commentaires

Je ne suis pas sûr du problème, mais une meilleure façon de faire une animation infinie est d'utiliser uiviewanimationOptionRepeat | UIViewanimationOptionAutOververeververeverse options. Pour terminer, ajoutez simplement une petite animation à la valeur d'extrémité souhaitée avec uiviewanimationOptionbeginfromCurrentState .


Merci, je connaissais cette option. Je veux juste finir des animations "bien". Si je serai définir isanimated = no - chaque cycle d'animation s'arrête après la fin. Donc, toutes les vues seront fanées après cela. Dans votre cas, je pense que je devrai arrêter immédiatement les animations.


Pas immédiatement, si vous démarrez une autre animation (non répétée) pour la décolorer, elle s'éloignera bien et lente. Mais oui, cela ne sera pas "aligné" aux cycles d'animation précédents.


Il peut être plus facile d'utiliser une minuterie et de ne pas utiliser le bloc d'achèvement.


@ Mar0ux merci. Mais comment saurai-je quelle sera la durée de la "petite animation" à la fin? Je veux dire quand j'arrête l'animation Toutes les vues sont dans différentes "phases". Donc, j'ai besoin de savoir que dois-je décolorer, puis disparaître, ou simplement disparaître. De plus, j'ai besoin de savoir le temps laissé pour chaque vue (<1.2). Je ne peux pas voir un moyen raisonnablement facile de faire ça ...


Alors, pourquoi ne commencez-vous pas simplement les animations tout à la fois mais passez 0,0, 0,2 et 0,4 à l'argument retard argument de + [UIView Animatedduration: Délai: Options: Animations: Achèvement:] ? Vous pouvez également passer le même bloc d'animation 3 fois. Ou, vous pouvez essayer la solution que j'ai proposée. Je ne sais pas comment vous pouvez voir les animations infinies Voir l'API UIView .


@Orogreswamp est votre dernière modification - êtes-vous sûr que les trucs de réseau ne se produisent pas sur le fil principal? Un moyen (légèrement hacable) de déterminer le temps restant pour la dernière animation est de calculer la phase basée sur la valeur alpha intermittente pendant que les vues s'animent.


@NeilSbot Je fais exactement la même chose - qui passe 0,0, 0,2 et 0,4 à retarder. Comme vous pouvez le voir dans mon premier exemple. Mais parce que les vues animées indépendamment tout retard dans la file d'attente provoquent la nonyncronisation des animations.


5 Réponses :


-2
votes

Essayez ceci, cela pourrait fonctionner pour vous.

- (void)playAnimation {
    isAnimated = YES;

    [self performSelector:@selector(animateView:) withObject:firstView afterDelay:0.1];
    [self performSelector:@selector(animateView:) withObject:secondView afterDelay:0.2];
    [self performSelector:@selector(animateView:) withObject:thirdView afterDelay:0.4];
}


- (void)animateView:(UIView *)animatedView {
   //Here "animatedView" will contain (firstView/secondView/thirdView) whatever you are passing
   //your animation
}


1 commentaires

Ohh..solire je n'ai pas remarqué ça.



0
votes

Essayez au lieu de performerSelector: l'exemple suivant

- (void)animateView:(UIView *)animatedView afterDelay:(float)delay {
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        if(isAnimated) {
            [UIView animateWithDuration:0.6 delay:0.0 options:UIViewAnimationOptionTransitionNone
                         animations:^ {
                animatedView.alpha = 1.0;
            } completion:^(BOOL finished) {
                [UIView animateWithDuration:0.6 animations:^ {
                    animatedView.alpha = 0.0;
                } completion:^(BOOL finished) {
                    [self animateView:animatedView afterDelay:0.0];
                }];
            }];
        }
    });
}


0 commentaires

1
votes

Le moyen de planifier les animations correctement consiste à utiliser le protocole Camediatiming que la classe CakeyFrameanimation est conforme à. Voir ma réponse ci-dessous pour des liens vers des ressources sur la manière de y parvenir.

Changement de vitesse d'une animation de gâteyFreanimation en cours


0 commentaires

0
votes

J'espère que cela fonctionnera comme ce que vous voulez.

- (void)animateView:(UIView *)animatedView afterDelay:(float)delay
{
    if(isAnimated) {
        [UIView animateWithDuration:0.6 delay:delay options:UIViewAnimationOptionTransitionNone
                         animations:^ {
                             animatedView.alpha = 1.0;
                         } completion:^(BOOL finished) {
                             [UIView animateWithDuration:0.6 delay:delay options:UIViewAnimationOptionTransitionNone animations:^{
                                  animatedView.alpha = 0.0;
                             } completion:^(BOOL finished) {
                                 [self animateView:animatedView afterDelay:delay];
                             }];
                         }];
    }
}


0 commentaires

10
votes

On dirait que vous voulez la même animation, appliquée à toutes les 3 vues, décalée par T = 0,2. Vous pouvez utiliser une animation de base pour faire exactement ce que vous voulez avec très peu d'effort.

le faire de cette façon, ils seront toujours chronométrés correctement. P>

Je propose ceci: p>

-(void)playAnimation
{
    CABasicAnimation * anim = [ CABasicAnimation animationWithKeyPath:@"opacity" ] ;
    anim.autoreverses = YES ;
    anim.repeatCount = CGFLOAT_MAX ;
    anim.removedOnCompletion = NO ;
    anim.duration = 0.6 ;
    anim.fromValue = @0.0 ;
    anim.toValue = @1.0;

    // finish configuring your animation here (timing function, speed, duration, fill mode, etc) ...

    CFTimeInterval t = CACurrentMediaTime() ;

    anim.beginTime = t ;
    [ self.firstView.layer addAnimation:anim forKey:@"opacity-anim" ] ; // name is so you can remove this anim later

    anim.beginTime += 0.2 ;
    [ self.secondView.layer addAnimation:anim forKey:@"opacity-anim" ] ;

    anim.beginTime += 0.2 ;
    [ self.thirdView.layer addAnimation:anim forKey:@"opacity-anim" ] ; // name is so you can remove this anim later
}

-(void)stopAnimation
{
    [ self.firstView.layer removeAnimationForKey:@"opacity-anim" ] ;
    [ self.secondView.layer removeAnimationForKey:@"opacity-anim" ] ;
    [ self.thirdView.layer removeAnimationForKey:@"opacity-anim" ] ;
}


10 commentaires

allait écrire quelque chose de similaire, me battait-moi :)


Pour gérer le fondu lisse après avoir retiré les animations répétées, de nouvelles animations publicitaires avec TOValue = 0. Ça devrait le faire. Chaque animation peut également avoir un délégué qui vous dira lorsque les animations sont terminées.


Merci. Cette solution fonctionne pour moi. Vous avez besoin de disparaître lisse, alors je vais mettre en œuvre cela aussi.


Allouera une prime dans 4 heures (donc ne me permettra pas de le faire maintenant)


@nielsbot essayait de mettre en œuvre une transition en douceur. L'appel d'arrêt peut être déclenché à tout moment. Nous ne savons donc pas quel est l'état actuel de l'alpha pour chaque point. Disons "STOP" a été déclenchée à 1,8s dans le graphique. Je veux que la dernière vue s'estompait à 1,0 et de disparaître. Donc, la durée d'animation pour la dernière vue sera de 1s. Je ne connais pas vraiment l'animation pour la dernière disparition. Une idée de la manière dont cela peut être mis en œuvre?


Il sera délicat de l'avoir animé à un cycle complet. Vous pouvez vous arrêter à 0 à partir de l'opacité actuelle: ajoutez une nouvelle cabasicanimation pour Alpha, avec FromValue = [Couche PrésentationLayer] .Opacity et TOValue = 0. Définissez la FLUTMODE sur «TIX», Ajoutez cette animation, puis retirez l'animation actuelle.


La seule autre chose à laquelle je passe est de planifier la suppression des animations à l'aide d'un NSTIMER. Demandez à la minuterie de réveiller au moment où vous souhaitez que votre animation soit supprimée (après avoir terminé le prochain cycle complet pour chaque couche) ... Vous pouvez obtenir un artefact visuel cependant si la minuterie est retardée, etc.


Y a-t-il un moyen de déclencher le délégué à la fin du cycle d'animation?


L'avez-vous essayé? Pas sûr s'il est appelé à chaque fois ou pas. Vous pouvez également essayer de supprimer l'animation que vous souhaitez mettre finner et l'ajoutez-le avec RepeatCount défini sur 1 de plus que le nombre actuel de cycles. Il y a un moyen de le faire. Je sais cependant que pour synchroniser vos animations correctement, vous devriez compter sur cette méthode. Bonne chance.


En fait, je pense que vous devriez demander à un autre Q sur Donc, non?