UIView隐藏/显示animation

我简单的目标是淡入淡出隐藏和显示function。

Button.hidden = YES; 

很简单。 但是,它可能会淡出而不是消失? 这样看起来相当不专业。

在iOS 4和更高版本中,只需使用UIView转换方法就可以做到这一点,而无需导入QuartzCore。 你可以说:

 [UIView transitionWithView:button duration:0.4 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{ button.hidden = YES; } completion:NULL]; 

先前的scheme

Michail的解决scheme将起作用,但实际上并不是最好的方法。

阿尔法衰落的问题是,有时不同的重叠视图图层看起来很奇怪,因为它们淡出。 有一些其他的select使用核心animation。 首先在您的应用程序中包含QuartzCore框架,并将#import <QuartzCore/QuartzCore.h>到您的标题中。 现在您可以执行以下任一操作:

1)set button.layer.shouldRasterize = YES; 然后使用Michail在答案中提供的alphaanimation代码。 这样可以防止图层混淆,但会有轻微的性能损失,并且如果button在像素边界上不完全alignment,可能会使button看起来模糊不清。

或者:

2)使用下面的代码来代替淡入淡出:

 CATransition *animation = [CATransition animation]; animation.type = kCATransitionFade; animation.duration = 0.4; [button.layer addAnimation:animation forKey:nil]; button.hidden = YES; 

这种方法的好处是你可以交叉淡入任何属性的button,即使他们不是animation(例如button的文本或图像),只需设置过渡,然后立即设置属性。

淡出:

 [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: UIView.animateWithDuration(0.3, animations: { button.alpha = 0 }) { (finished) in button.hidden = finished } 

淡入:

 button.alpha = 0; button.hidden = NO; [UIView animateWithDuration:0.3 animations:^{ button.alpha = 1; }]; // swift: button.alpha = 0 button.hidden = false UIView.animateWithDuration(0.3) { button.alpha = 1 } 

最好的办法:

Swift 3:

 func setView(view: UIView, hidden: Bool) { UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: { _ in view.isHidden = hidden }, completion: nil) } 

Swift 2:

 func setView(view: UIView, hidden: Bool) { UIView.transitionWithView(view, duration: 0.5, options: .TransitionCrossDissolve, animations: {() -> Void in view.hidden = hidden }, completion: nil) } 

目标C:

 - (void)setView:(UIView*)view hidden:(BOOL)hidden { [UIView transitionWithView:view duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^(void){ [view setHidden:hidden]; } completion:nil]; } 

为此我创build了UIView类别,并实现了一个特殊的一点点不同的概念: visibility 。 我的解决scheme的主要区别是,你可以调用[view setVisible:NO animated:YES] ,然后同步检查[view visible]并得到正确的结果。 这很简单,但非常有用。

此外,还可以避免使用“负布尔逻辑”(请参见第269页的“完整代码”,了解更多信息,请参阅使用正布尔variables名称 )。

迅速

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 } } 

Objective-C的

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 

Swift 3

 func appearView() { self.myView.alpha = 0 self.myView.isHidden = false UIView.animate(withDuration: 0.9, animations: { self.myView.alpha = 1 }, completion: { finished in self.myView.isHidden = false }) } 

我使用这个小小的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) } } 

你可以很容易地使用Animatics库:

 //To hide button: AlphaAnimator(0) ~> button //to show button AlphaAnimator(1) ~> button 

我的解决scheme为Swift 3 。 所以,我创build了这个函数,隐藏/取消隐藏视图以正确的顺序(当隐藏 – 将alpha设置为0,然后isHidden为true;取消隐藏 – 首先显示视图,然后将其设置为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) } 
 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 }) } 

迅速4过渡

  UIView.transition(with: view, duration: 3, options: .transitionCurlDown, animations: { // Animations view.isHidden = hidden }, completion: { finished in // Compeleted }) 

如果您使用较旧的swift版本的方法,你会得到一个错误:

 Cannot convert value of type '(_) -> ()' to expected argument type '(() -> Void)?' 

有用的参考 。