Réponses:
Dans iOS 4 et versions ultérieures, il existe un moyen de le faire en utilisant simplement la méthode de transition UIView sans avoir besoin d'importer QuartzCore. Vous pouvez simplement dire:
[UIView transitionWithView:button
duration:0.4
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
button.hidden = YES;
}
completion:NULL];
UIView.transition(with: button, duration: 0.4,
options: .transitionCrossDissolve,
animations: {
button.hidden = false
})
La solution de Michail fonctionnera, mais ce n'est pas vraiment la meilleure approche.
Le problème avec le fondu alpha est que parfois les différentes couches de vue qui se chevauchent semblent étranges lorsqu'elles disparaissent. Il existe d'autres alternatives utilisant Core Animation. Incluez d'abord le framework QuartzCore dans votre application et ajoutez-le #import <QuartzCore/QuartzCore.h>
à votre en-tête. Vous pouvez maintenant effectuer l'une des opérations suivantes:
1) définissez button.layer.shouldRasterize = YES;
puis utilisez le code d'animation alpha que Michail a fourni dans sa réponse. Cela empêchera les calques de se mélanger de manière étrange, mais entraînera une légère pénalité en termes de performances et peut rendre le bouton flou s'il n'est pas aligné exactement sur une limite de pixel.
Alternativement:
2) Utilisez le code suivant pour animer le fondu à la place:
CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.duration = 0.4;
[button.layer addAnimation:animation forKey:nil];
button.hidden = YES;
La bonne chose à propos de cette approche est que vous pouvez fondre toutes les propriétés du bouton même si elles ne peuvent pas être animées (par exemple, le texte ou l'image du bouton), configurez simplement la transition et définissez vos propriétés immédiatement après.
transitionWithView
paramètre pour garantir un fondu entrant et sortant réussi.
Les propriétés animées UIView sont:
- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch
Décrivez dans: Animations
isHidden
n'est pas l'un d'entre eux, donc selon moi, le meilleur moyen est:
Swift 4:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
Objectif c:
- (void)setView:(UIView*)view hidden:(BOOL)hidden {
[UIView transitionWithView:view duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^(void){
[view setHidden:hidden];
} completion:nil];
}
Pour disparaître:
Objectif c
[UIView animateWithDuration:0.3 animations:^{
button.alpha = 0;
} completion: ^(BOOL finished) {//creates a variable (BOOL) called "finished" that is set to *YES* when animation IS completed.
button.hidden = finished;//if animation is finished ("finished" == *YES*), then hidden = "finished" ... (aka hidden = *YES*)
}];
Swift 2
UIView.animateWithDuration(0.3, animations: {
button.alpha = 0
}) { (finished) in
button.hidden = finished
}
Swift 3, 4, 5
UIView.animate(withDuration: 0.3, animations: {
button.alpha = 0
}) { (finished) in
button.isHidden = finished
}
Pour s'estomper:
Objectif c
button.alpha = 0;
button.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
button.alpha = 1;
}];
Swift 2
button.alpha = 0
button.hidden = false
UIView.animateWithDuration(0.3) {
button.alpha = 1
}
Swift 3, 4, 5
button.alpha = 0
button.isHidden = false
UIView.animate(withDuration: 0.3) {
button.alpha = 1
}
J'utilise cette petite extension Swift 3 :
extension UIView {
func fadeIn(duration: TimeInterval = 0.5,
delay: TimeInterval = 0.0,
completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
UIView.animate(withDuration: duration,
delay: delay,
options: UIViewAnimationOptions.curveEaseIn,
animations: {
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5,
delay: TimeInterval = 0.0,
completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
UIView.animate(withDuration: duration,
delay: delay,
options: UIViewAnimationOptions.curveEaseIn,
animations: {
self.alpha = 0.0
}, completion: completion)
}
}
rapide 4.2
avec extension:
extension UIView {
func hideWithAnimation(hidden: Bool) {
UIView.transition(with: self, duration: 0.5, options: .transitionCrossDissolve, animations: {
self.isHidden = hidden
})
}
}
méthode simple:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
Utilisez cette solution pour des effets de fondu et de fondu en douceur
extension UIView {
func fadeIn(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.isHidden = false
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
self.alpha = 1.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseOut, animations: {
self.isHidden = true
self.alpha = 0.0
}, completion: completion)
}
}
l'utilisation est comme
uielement.fadeIn()
uielement.fadeOut()
Merci
fadeOut
fonctionne sur iOS 13 uniquement si je supprime les lignes définies self.isHidden
.
J'ai créé pour la catégorie UIView
à cet effet et mis en œuvre un peu spécial bit concept différent: visibility
. La principale différence de ma solution est que vous pouvez appeler [view setVisible:NO animated:YES]
et juste après cette vérification synchrone [view visible]
et obtenir un résultat correct. C'est assez simple mais extrêmement utile.
De plus, il est permis d'éviter d'utiliser la "logique booléenne négative" (voir Code complet, page 279, Utiliser des noms de variables booléennes positifs pour plus d'informations).
UIView+Visibility.swift
import UIKit
private let UIViewVisibilityShowAnimationKey = "UIViewVisibilityShowAnimationKey"
private let UIViewVisibilityHideAnimationKey = "UIViewVisibilityHideAnimationKey"
private class UIViewAnimationDelegate: NSObject {
weak var view: UIView?
dynamic override func animationDidStop(animation: CAAnimation, finished: Bool) {
guard let view = self.view where finished else {
return
}
view.hidden = !view.visible
view.removeVisibilityAnimations()
}
}
extension UIView {
private func removeVisibilityAnimations() {
self.layer.removeAnimationForKey(UIViewVisibilityShowAnimationKey)
self.layer.removeAnimationForKey(UIViewVisibilityHideAnimationKey)
}
var visible: Bool {
get {
return !self.hidden && self.layer.animationForKey(UIViewVisibilityHideAnimationKey) == nil
}
set {
let visible = newValue
guard self.visible != visible else {
return
}
let animated = UIView.areAnimationsEnabled()
self.removeVisibilityAnimations()
guard animated else {
self.hidden = !visible
return
}
self.hidden = false
let delegate = UIViewAnimationDelegate()
delegate.view = self
let animation = CABasicAnimation(keyPath: "opacity")
animation.fromValue = visible ? 0.0 : 1.0
animation.toValue = visible ? 1.0 : 0.0
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
animation.delegate = delegate
self.layer.addAnimation(animation, forKey: visible ? UIViewVisibilityShowAnimationKey : UIViewVisibilityHideAnimationKey)
}
}
func setVisible(visible: Bool, animated: Bool) {
let wereAnimationsEnabled = UIView.areAnimationsEnabled()
if wereAnimationsEnabled != animated {
UIView.setAnimationsEnabled(animated)
defer { UIView.setAnimationsEnabled(!animated) }
}
self.visible = visible
}
}
UIView+Visibility.h
#import <UIKit/UIKit.h>
@interface UIView (Visibility)
- (BOOL)visible;
- (void)setVisible:(BOOL)visible;
- (void)setVisible:(BOOL)visible animated:(BOOL)animated;
@end
UIView+Visibility.m
#import "UIView+Visibility.h"
NSString *const UIViewVisibilityAnimationKeyShow = @"UIViewVisibilityAnimationKeyShow";
NSString *const UIViewVisibilityAnimationKeyHide = @"UIViewVisibilityAnimationKeyHide";
@implementation UIView (Visibility)
- (BOOL)visible
{
if (self.hidden || [self.layer animationForKey:UIViewVisibilityAnimationKeyHide]) {
return NO;
}
return YES;
}
- (void)setVisible:(BOOL)visible
{
[self setVisible:visible animated:NO];
}
- (void)setVisible:(BOOL)visible animated:(BOOL)animated
{
if (self.visible == visible) {
return;
}
[self.layer removeAnimationForKey:UIViewVisibilityAnimationKeyShow];
[self.layer removeAnimationForKey:UIViewVisibilityAnimationKeyHide];
if (!animated) {
self.alpha = 1.f;
self.hidden = !visible;
return;
}
self.hidden = NO;
CGFloat fromAlpha = visible ? 0.f : 1.f;
CGFloat toAlpha = visible ? 1.f : 0.f;
NSString *animationKey = visible ? UIViewVisibilityAnimationKeyShow : UIViewVisibilityAnimationKeyHide;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.duration = 0.25;
animation.fromValue = @(fromAlpha);
animation.toValue = @(toAlpha);
animation.delegate = self;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[self.layer addAnimation:animation forKey:animationKey];
}
#pragma mark - CAAnimationDelegate
- (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished
{
if ([[self.layer animationForKey:UIViewVisibilityAnimationKeyHide] isEqual:animation]) {
self.hidden = YES;
}
}
@end
le code de @Umair Afzal fonctionne bien dans Swift 5 après quelques changements
extension UIView {
func fadeIn(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.isHidden = false
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
self.alpha = 1.0
UIView.animate(withDuration: duration, delay: delay, options: UIView.AnimationOptions.curveEaseIn, animations: {
self.alpha = 0.0
}) { (completed) in
self.isHidden = true
completion(true)
}
}
}
pour utilisation
yourView.fadeOut()
yourView.fadeIn()
Swift 4
extension UIView {
func fadeIn(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in }) {
self.alpha = 0.0
UIView.animate(withDuration: duration, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.isHidden = false
self.alpha = 1.0
}, completion: completion)
}
func fadeOut(duration: TimeInterval = 0.5, delay: TimeInterval = 0.0, completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in }) {
self.alpha = 1.0
UIView.animate(withDuration: duration, delay: delay, options: UIViewAnimationOptions.curveEaseIn, animations: {
self.alpha = 0.0
}) { (completed) in
self.isHidden = true
completion(true)
}
}
}
Et pour l'utiliser, appelez simplement ces fonctions comme:
yourView.fadeOut() // this will hide your view with animation
yourView.fadeIn() /// this will show your view with animation
isHidden
est une valeur immédiate et vous ne pouvez pas affecter une animation dessus, au lieu de cela, vous pouvez utiliser Alpha pour masquer votre vue
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 0
})
Et pour montrer:
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 1
})
Vous pouvez le faire TRÈS facilement en utilisant la bibliothèque Animatics :
//To hide button:
AlphaAnimator(0) ~> button
//to show button
AlphaAnimator(1) ~> button
func flipViews(fromView: UIView, toView: UIView) {
toView.frame.origin.y = 0
self.view.isUserInteractionEnabled = false
UIView.transition(from: fromView, to: toView, duration: 0.5, options: .transitionFlipFromLeft, completion: { finished in
fromView.frame.origin.y = -900
self.view.isUserInteractionEnabled = true
})
}
Vous pouvez essayer ceci.
func showView(objView:UIView){
objView.alpha = 0.0
UIView.animate(withDuration: 0.5, animations: {
objView.alpha = 0.0
}, completion: { (completeFadein: Bool) -> Void in
objView.alpha = 1.0
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade
objView.layer.add(transition, forKey: nil)
})
}
func HideView(objView:UIView){
UIView.animate(withDuration: 0.5, animations: {
objView.alpha = 1.0
}, completion: { (completeFadein: Bool) -> Void in
objView.alpha = 0.0
let transition = CATransition()
transition.duration = 0.5
transition.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
transition.type = kCATransitionFade
objView.layer.add(transition, forKey: nil)
})
}
Et passez votre nom de vue
showView(objView: self.viewSaveCard)
HideView(objView: self.viewSaveCard)
Si votre vue est définie sur Caché par défaut ou si vous modifiez l'état Caché, ce que je pense que vous devriez dans de nombreux cas, aucune des approches de cette page ne vous donnera à la fois une animation FadeIn / FadeOut, elle n'animera qu'un de ces états, la raison en est que vous définissez l'état Caché sur false avant d'appeler UIView.animate méthode , ce qui provoquera une visibilité soudaine et si vous que l'alpha, l'espace objet est toujours là mais il n'est pas visible, ce qui entraînera des problèmes d'interface utilisateur.
La meilleure approche consiste donc à vérifier d'abord si la vue est masquée, puis à définir l'alpha sur 0,0, comme ceci lorsque vous définissez l'état Caché sur false, vous ne verrez pas une visibilité soudaine.
func hideViewWithFade(_ view: UIView) {
if view.isHidden {
view.alpha = 0.0
}
view.isHidden = false
UIView.animate(withDuration: 0.3, delay: 0.0, options: .transitionCrossDissolve, animations: {
view.alpha = view.alpha == 1.0 ? 0.0 : 1.0
}, completion: { _ in
view.isHidden = !Bool(truncating: view.alpha as NSNumber)
})
}
La fonction UIView.transition (avec :) est agréable et soignée.
Beaucoup l'ont publié, mais aucun n'a remarqué qu'il y a une erreur qui n'apparaîtra que lorsque vous l'exécuterez.
Vous pouvez parfaitement faire passer la propriété cachée à true, tandis que lorsque vous tentez de la faire passer à false, la vue disparaîtra soudainement sans aucune animation.
En effet, cette API ne fonctionne que dans une vue, ce qui signifie que lorsque vous passez d'une vue à afficher, en fait elle-même s'affiche immédiatement, seul son contenu est animé progressivement.
Lorsque vous essayez de masquer cette vue, elle-même se cache tout de suite, rend l'animation à son contenu sans signification.
Pour résoudre ce problème, lorsque vous masquez une vue, la cible de la transition doit être sa vue parente au lieu de la vue que vous souhaitez masquer.
func transitionView(_ view: UIView?, show: Bool, completion: BoolFunc? = nil) {
guard let view = view, view.isHidden == show, let parent = view.superview else { return }
let target: UIView = show ? view : parent
UIView.transition(with: target, duration: 0.4, options: [.transitionCrossDissolve], animations: {
view.isHidden = !show
}, completion: completion)
}
Ma solution pour Swift 3 . Donc, j'ai créé la fonction, qui cache / affiche la vue dans le bon ordre (lors du masquage - définissez alpha sur 0 puis isHidden sur true; unhiding - révélez d'abord la vue, puis définissez son alpha sur 1):
func hide(_ hide: Bool) {
let animations = hide ? { self.alpha = 0 } :
{ self.isHidden = false }
let completion: (Bool) -> Void = hide ? { _ in self.isHidden = true } :
{ _ in UIView.animate(withDuration: duration, animations: { self.alpha = 1 }) }
UIView.animate(withDuration: duration, animations: animations, completion: completion)
}
completion
bloc il y a une autre animation quand hide
est faux?
Transition Swift 4
UIView.transition(with: view, duration: 3, options: .transitionCurlDown,
animations: {
// Animations
view.isHidden = hidden
},
completion: { finished in
// Compeleted
})
Si vous utilisez l'approche pour les anciennes versions de Swift, vous obtiendrez une erreur:
Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?'
Référence utile .
isHidden
valeur est rendue instantanément (c.-à-d. masquant / affichant instantanément la vue).
Ce code donne une animation comme pousser viewController dans le contrôleur uinavigation ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromRight;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = true;
Utilisé ceci pour l'animation pop ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromLeft;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = false;
J'ai essayé certaines des réponses abandonnées, certaines ne fonctionnent que pour une situation, certaines d'entre elles doivent ajouter deux fonctions.
Option 1
Rien à voir avec view.isHidden
.
extension UIView {
func animate(fadeIn: Bool, withDuration: TimeInterval = 1.0) {
UIView.animate(withDuration: withDuration, delay: 0.0, options: .curveEaseInOut, animations: {
self.alpha = fadeIn ? 1.0 : 0.0
})
}
}
Puis passe isFadeIn
( true
ou false
)
view.animate(fadeIn: isFadeIn)
Option 2
Ne passez aucun paramètre. Il s'estompe ou disparaît selon isUserInteractionEnabled
. Cela convient également très bien à la situation animée d'avant en arrière.
func animateFadeInOut(withDuration: TimeInterval = 1.0) {
self.isUserInteractionEnabled = !self.isUserInteractionEnabled
UIView.animate(withDuration: withDuration, delay: 0.0, options: .curveEaseInOut, animations: {
self.alpha = self.isUserInteractionEnabled ? 1.0 : 0.0
})
}
Alors tu appelles
yourView.animateFadeInOut()
Pourquoi
self.isUserInteractionEnabled
?J'ai essayé de remplacer
self.isUserInteractionEnabled
parself.isHidden
, pas de chance du tout.
C'est tout. Ça me coûte du temps, j'espère que ça aide quelqu'un.