Respuestas:
En iOS 4 y versiones posteriores, hay una manera de hacer esto simplemente usando el método de transición UIView sin necesidad de importar QuartzCore. Solo puedes decir:
[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 solución de Michail funcionará, pero en realidad no es el mejor enfoque.
El problema con el desvanecimiento alfa es que a veces las diferentes capas de vista superpuestas se ven extrañas a medida que se desvanecen. Hay algunas otras alternativas que usan Core Animation. Primero incluya el marco QuartzCore en su aplicación y agréguelo #import <QuartzCore/QuartzCore.h>
a su encabezado. Ahora puede hacer uno de los siguientes:
1) establezca button.layer.shouldRasterize = YES;
y luego use el código de animación alfa que Michail proporcionó en su respuesta. Esto evitará que las capas se mezclen extrañamente, pero tiene una ligera penalización de rendimiento y puede hacer que el botón se vea borroso si no está alineado exactamente en un límite de píxeles.
Alternativamente:
2) Use el siguiente código para animar el desvanecimiento en su lugar:
CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.duration = 0.4;
[button.layer addAnimation:animation forKey:nil];
button.hidden = YES;
Lo bueno de este enfoque es que puede hacer un fundido cruzado de cualquier propiedad del botón, incluso si no son animables (por ejemplo, el texto o la imagen del botón), simplemente configure la transición y luego configure sus propiedades inmediatamente después.
transitionWithView
parámetro para garantizar un fundido de entrada y salida exitoso.
Las propiedades animadas de UIView son:
- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch
Describa en: animaciones
isHidden
no es uno de ellos, así que, según veo, la mejor manera es:
Swift 4:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
C objetivo:
- (void)setView:(UIView*)view hidden:(BOOL)hidden {
[UIView transitionWithView:view duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^(void){
[view setHidden:hidden];
} completion:nil];
}
Para desvanecerse:
C objetivo
[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
}
Para desvanecerse en:
C objetivo
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
}
Yo uso esta pequeña extensión de 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)
}
}
swift 4.2
con extensión:
extension UIView {
func hideWithAnimation(hidden: Bool) {
UIView.transition(with: self, duration: 0.5, options: .transitionCrossDissolve, animations: {
self.isHidden = hidden
})
}
}
método simple:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
Use esta solución para obtener efectos suaves de fadeOut y fadeIn
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)
}
}
el uso es como
uielement.fadeIn()
uielement.fadeOut()
Gracias
fadeOut
funciona en iOS 13 solo si elimino las líneas que establecen self.isHidden
.
He creado una categoría para UIView
este fin y puso en práctica un poco especial poco diferente concepto: visibility
. La principal diferencia de mi solución es que puede llamar [view setVisible:NO animated:YES]
y justo después de eso verificar sincrónicamente [view visible]
y obtener el resultado correcto. Esto es bastante simple pero extremadamente útil.
Además, se permite evitar el uso de "lógica booleana negativa" (consulte Código completo, página 269, Usar nombres de variable booleana positiva para obtener más información).
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
El código de @Umair Afzal funciona bien en Swift 5 después de algunos cambios
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)
}
}
}
para usar
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)
}
}
}
Y para usarlo, simplemente llame a estas funciones como:
yourView.fadeOut() // this will hide your view with animation
yourView.fadeIn() /// this will show your view with animation
isHidden
es un valor inmediato y no puede afectar una animación en él, en lugar de esto puede usar Alpha para ocultar su vista
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 0
})
Y por mostrar:
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.alpha = 1
})
Puedes hacerlo MUY fácilmente usando la biblioteca 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
})
}
Puedes probar esto.
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)
})
}
Y pasa tu nombre de vista
showView(objView: self.viewSaveCard)
HideView(objView: self.viewSaveCard)
Si su vista está configurada como oculta de manera predeterminada o si cambia el estado Oculto, lo que creo que debería hacer en muchos casos, ninguno de los enfoques en esta página le proporcionará animación FadeIn / FadeOut, solo animará uno de estos estados, la razón es que está configurando el estado Oculto en falso antes de llamar al método UIView.animate , lo que causará una visibilidad repentina y si solo anima el alfa, el espacio del objeto todavía está allí, pero no es visible, lo que provocará algunos problemas de IU.
Entonces, el mejor enfoque es verificar primero si la vista está oculta y luego establecer el alfa en 0.0, de esta manera cuando establece el estado Oculto en falso, no verá una visibilidad repentina.
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)
})
}
UIView.transition (con :) la función es agradable y ordenada.
Muchos lo han publicado, pero ninguno se ha dado cuenta de que existe una falla que se mostrará solo cuando lo ejecute.
Puede pasar la propiedad oculta a verdadero perfectamente, mientras que cuando intente hacer la transición a falso, la vista simplemente desaparecerá repentinamente sin ninguna animación.
Esto se debe a que esta API solo funciona dentro de una vista, lo que significa que cuando hace la transición de una vista para mostrar, de hecho, se muestra de inmediato, solo su contenido se anima gradualmente.
Cuando intenta ocultar esta vista, se oculta de inmediato, hace que la animación de su contenido no tenga sentido.
Para resolver esto, al ocultar una vista, el objetivo de transición debe ser su vista principal en lugar de la vista que desea ocultar.
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)
}
Mi solución para Swift 3 . Entonces, creé la función, que oculta / muestra la vista en el orden correcto (cuando se oculta, establece alfa en 0 y luego se oculta en verdadero; oculta: primero revela la vista y luego establece su alfa en 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
bloque hay otra animación cuando hide
es falsa?
Transición Swift 4
UIView.transition(with: view, duration: 3, options: .transitionCurlDown,
animations: {
// Animations
view.isHidden = hidden
},
completion: { finished in
// Compeleted
})
Si utiliza el enfoque para versiones rápidas anteriores, obtendrá un error:
Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?'
Útil de referencia .
isHidden
valor se representa instantáneamente (es decir, ocultando / mostrando instantáneamente la vista).
Este código da una animación como presionar viewController en un controlador de navegación ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromRight;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = true;
Lo usé para la animación pop ...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromLeft;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = false;
Intenté algunas de las respuestas salidas, algunas solo funcionan para una situación, algunas de ellas necesitan agregar dos funciones.
Opción 1
Nada que ver con 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
})
}
}
Luego pasa isFadeIn
( true
o false
)
view.animate(fadeIn: isFadeIn)
opcion 2
No pase ningún parámetro. Se desvanece dentro o fuera de acuerdo con isUserInteractionEnabled
. Esto también se adapta muy bien a la situación animada de un lado a otro.
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
})
}
Entonces llamas
yourView.animateFadeInOut()
¿Por qué
self.isUserInteractionEnabled
?Intentado sustituir
self.isUserInteractionEnabled
porself.isHidden
, sin suerte en absoluto.
Eso es. Me costó alguna vez, espero que ayude a alguien.