web-dev-qa-db-fra.com

Comment ajouter une animation en changeant le mode caché d'un uiview?

Je souhaite ajouter une animation à une vue tout en modifiant son mode masqué, c.-à-d.

my_view.hidden=YES;

J'ai ajouté un bouton dans la barre de navigation. Lorsque nous cliquons dessus, la nouvelle vue est affichée. Il dessine en haut de la table de navigation. 

39
Sanchit Paurush

Malheureusement, masqué n'est pas une propriété pouvant être animée via des animations UIView. Je pense que votre meilleur choix est d’utiliser l’une des animations suggérées par @Erik B ou de commencer à jouer avec les Core Animations, qui sont beaucoup plus puissantes. Jetez un coup d'œil à la documentation des animations UIView et Core Animations.

J'ai réalisé quelque chose comme ce que vous suggérez en utilisant des animations UIView pour faire glisser la nouvelle vue de dessous une autre vue. Cela donnait l'impression d'un tiroir coulissant. Si vous voulez faire quelque chose comme ça, vous devez intercepter l'événement de retouche à l'intérieur et y placer le code d'animation.

- (IBAction)buttonClicked:(id)sender {
    [UIView animateWithDuration:0.5
                          delay:0.0 
                        options:UIViewAnimationCurveEaseOut
                     animations:^(void) {
                        self.myView.frame = /* set the frame here */
                     } 
                     completion:NULL];
}
29
Eytan

Animez l'opacité de la vue de 100% à 0%. Demandez au rappel d'achèvement de l'animation de masquer la vue. Vous pouvez également vouloir réinitialiser l'opacité à 100% pendant le rappel, afin que la vue apparaisse complètement opaque lorsque vous la désactivez.

yourView.alpha = 0.0 //for zero opacity
yourView.alpha = 1.0 //for 100% opacity
54

Il n'y a pas d'animation pour se cacher cependant; vous obtenez le même résultat avec le code Swift ci-dessous:

UIView.animate(withDuration: 0.2, delay: 0, options: [], animations: {            
    self.yourView.alpha = 0 // Here you will get the animation you want
}, completion: { _ in  
    self.yourView.hidden = true // Here you hide it when animation done
})
28
Palyancodr

Mis à jour à Swift 3 :

UIView.animate(withDuration: 0.2, delay: 0.2, options: .curveEaseOut,
      animations: {firstView.alpha = 0}, 
      completion: { _ in firstView.isHidden = true
        //Do anything else that depends on this animation ending
    })

Et si vous souhaitez animer quelque chose après la première vue, vous pouvez répliquer le code dans le bloc d'achèvement avec alpha = 1 et hidden = false.

19

Voici une catégorie que j'ai écrite pour introduire une nouvelle propriété "cachée" sur UIView qui supporte correctement l'animation:

@implementation UIView (AnimateHidden)

-(void)setHiddenAnimated:(BOOL)hide
{
  [UIView animateWithDuration:0.5
                        delay:0.0
                      options: UIViewAnimationCurveEaseOut
                   animations:^
                             {
                           [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
                           if (hide)
                             self.alpha=0;
                           else
                           {
                             self.hidden= NO;
                             self.alpha=1;
                           }
                         }
      completion:^(BOOL b)
      {
        if (hide)
          self.hidden= YES;
      }
  ];
}
@end
18
N.J.

Je pense que le moyen le plus approprié de le faire est:

[UIView transitionWithView:aView
                  duration:0.3
                   options:UIViewAnimationOptionTransitionCrossDissolve 
                animations:^(void){
                              aView.hidden = NO;
                           }
                completion:nil];
18
Abhi

Ceci est corrigé N.J. version:

@implementation UIView (AnimateHidden)

-(void)setHiddenAnimated:(BOOL)hide duration:(NSTimeInterval)duration {
    if(self.hidden == hide)
        return;
    if(hide)
        self.alpha = 1;
    else {
        self.alpha = 0;
        self.hidden = NO;
    }
    [UIView animateWithDuration:duration animations:^{
        if (hide)
            self.alpha = 0;
        else
            self.alpha = 1;
    } completion:^(BOOL finished) {
        if(finished)
            self.hidden = hide;
    }];
}

@end
9
Stan

Voici la version de Swift pour cela:

 UIView.animateWithDuration(0.5, delay: 0.2, options:
    UIViewAnimationOptions.CurveEaseOut, animations: {
            objView.alpha = 0
        }, completion: { finished in
            objView.hidden = true
  })

Ceci effectue une animation d'une durée de 5 secondes et après un délai de 2 secondes.

AnimationOptions disponibles sont:

CurveEaseInOut, CurveEaseIn, CurveEaseOut, CurveLinear
6
Jayprakash Dubey

Les réponses de NJ et de Stanislav ici m'ont aidé à créer une nouvelle catégorie, ce qui, je pense, améliore les réponses, alors je me suis dit que je publierais ce que j'ai écrit au cas où cela aiderait quelqu'un d'autre. 

Notez que cela ne fonctionnera que sur iOS4 ou version ultérieure, car il utilise des blocs.

UIView + AnimateHidden.m

#import "UIView+AnimateHidden.h"

@implementation UIView (AnimateHidden)

- (void)setHidden:(BOOL)hidden animated:(BOOL)animated
{
    // If the hidden value is already set, do nothing
    if (hidden == self.hidden) {
        return;
    }
    // If no animation requested, do the normal setHidden method
    else if (animated == NO) {
        [self setHidden:hidden];
        return;
    }
    else {
        // Store the view's current alpha value
        CGFloat origAlpha = self.alpha;

        // If we're unhiding the view, make it invisible initially
        if (hidden == NO) {
            self.alpha = 0;
        }

        // Unhide the view so we can see the animation
        self.hidden = NO;

        // Do the animation
        [UIView animateWithDuration:0.5
                              delay:0.0
                            options: UIViewAnimationOptionCurveEaseOut
                         animations:^{
            // Start animation block
            if (hidden == YES) {
                self.alpha = 0;
            }
            else {
                self.alpha = origAlpha;
            }
            // End animation block
        }
                        completion:^(BOOL b){
            // Start completion block
            // Finish up by hiding the view if necessary...
            self.hidden = hidden;
            // ... and putting back the correct alpha value
            self.alpha = origAlpha;
            // End completion block
        }];
    }
}

@end
3
Craig Brown

Étant donné que certaines de ces réponses sont un peu encombrées, j'ai pensé pouvoir publier mon design minimaliste de cette API. J'ai également ajouté le délai et la durée - car pourquoi pas.

Dans la mise en œuvre nous avons.

#import "UIView+AnimateHidden.h"

@implementation UIView (AnimateHidden)

- (void)setHiddenAnimated:(BOOL)hide
                    delay:(NSTimeInterval)delay
                 duration:(NSTimeInterval)duration {
    [UIView animateWithDuration:duration
                          delay:delay
                        options:UIViewAnimationOptionAllowAnimatedContent
                     animations:^{
                         if (hide) {
                             self.alpha = 0;
                         } else {
                             self.alpha = 0;
                             self.hidden = NO; // We need this to see the animation 0 -> 1
                             self.alpha = 1;
                         }
    } completion:^(BOOL finished) {
        self.hidden = hide;
    }];
}

@end

Dans le en-tête fichier que nous avons.

#import <UIKit/UIKit.h>

@interface UIView (AnimateHidden)

- (void)setHiddenAnimated:(BOOL)hide
                    delay:(NSTimeInterval)delay
                 duration:(NSTimeInterval)duration;

@end
3
Entalpi

Une autre version si vous souhaitez utiliser des types d’animation plus complexes ou des animations non supportées par UIView

- (void)setHidden:(BOOL)hidden withAnimationDuration:(NSTimeInterval)duration
{
    CATransition* transition = ({
        CATransition* its = [CATransition animation];
        its.duration = duration;
        its.timingFunction =
            [CAMediaTimingFunction
             functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
        its.type = kCATransitionPush;
        its.subtype = (hidden ? @"fromBottom" : @"fromTop");
        its
    });

    UIView* containerView = self.superview;
    [containerView.layer removeAllAnimations];
    [containerView.layer addAnimation: transition forKey: kCATransition];

    self.hidden = hidden;

    if (!hidden) {
        [self.superview bringSubviewToFront: self];
    }
}
0
Hofi

Voici le code que j'ai utilisé pour modéliser une vue "en croissance" et "en réduction" sur un bouton "Afficher plus ..." et "Afficher moins ...". Modélisé à partir de la réponse de Palyancodr 

Cette approche me permet de créer les deux vues dans le storyboard afin que les contraintes fonctionnent comme prévu sur les différents périphériques iOS et que je n'ai pas besoin de coder de manière personnalisée toutes les contraintes.

@IBAction func showMoreOrLessAction(_ sender: Any) {
    // if small view showing
    if showMoreLargeView.isHidden {
        showMoreSmallView.isHidden = true

        //showMoreLargeView.isHidden = false
        UIView.animate(withDuration: 0.2, delay: 0, options: [], animations: {
            self.showMoreLargeView.alpha = 1 // Here you will get the animation you want
        }, completion: { _ in
            self.showMoreLargeView.isHidden = false // Here you hide it when animation done
        })
    }
    else { // large view showing
        //showMoreSmallView.isHidden = false
        UIView.animate(withDuration: 0.2, delay: 0, options: [], animations: {
            self.showMoreSmallView.alpha = 1 // Here you will get the animation you want
        }, completion: { _ in
            self.showMoreSmallView.isHidden = false // Here you hide it when animation done
        })

        showMoreLargeView.isHidden = true
    }
}
0
Jacksonsox