UIView隐藏/显示动画

JTA*_*pps 141 objective-c uiviewanimation ios

我的简单目标是淡化隐藏和显示功能的动画.

Button.hidden = YES;
Run Code Online (Sandbox Code Playgroud)

很简单.但是,是否有可能让它淡出而不仅仅是消失?这样看起来相当不专业.

Nic*_*ood 245

在iOS 4及更高版本中,有一种方法可以使用UIView转换方法来执行此操作,而无需导入QuartzCore.你可以说:

[UIView transitionWithView:button
                  duration:0.4
                   options:UIViewAnimationOptionTransitionCrossDissolve
                animations:^{
                     button.hidden = YES;
                }
                completion:NULL];
Run Code Online (Sandbox Code Playgroud)

以前的方案

Michail的解决方案可行,但实际上并不是最好的方法.

alpha淡化的问题在于,有时不同的重叠视图层在淡出时看起来很奇怪.还有一些使用Core Animation的替代方案.首先在您的应用程序中包含QuartzCore框架并添加#import <QuartzCore/QuartzCore.h>到标题中.现在您可以执行以下操作之一:

1)设置button.layer.shouldRasterize = YES;然后使用Michail在他的答案中提供的alpha动画代码.这样可以防止图层奇怪地混合,但会有轻微的性能损失,并且如果按钮没有在像素边界上精确对齐,可能会使按钮看起来模糊.

或者:

2)使用以下代码为fade设置动画:

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

button.hidden = YES;
Run Code Online (Sandbox Code Playgroud)

这种方法的好处是你可以交叉淡化按钮的任何属性,即使它们不是可动画的(例如按钮的文本或图像),只需设置过渡,然后立即设置你的属性.

  • @robmathers,我只是测试你的代码,上面两个代码只是在button.hidden = NO时工作,用于淡入淡出的情况; 当button.hidden = YES时,淡出没有动画效果; (4认同)
  • 您应该将要制作动画的事物的超级视图用作“ transitionWithView”参数,以确保成功进行淡入和淡出。 (3认同)

evy*_*vya 151

UIView动画属性是:

- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch
Run Code Online (Sandbox Code Playgroud)

描述于: 动画

isHidden 不是其中之一,所以我认为最好的方法是:

斯威夫特4:

func setView(view: UIView, hidden: Bool) {
    UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
        view.isHidden = hidden
    })
}
Run Code Online (Sandbox Code Playgroud)

目标C:

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

  • 实际上这是简单而最好的答案 (8认同)
  • 此代码不起作用...它直接更改状态而不动画 (4认同)
  • 虽然这动画正确,但我试图显示的 UISearchBar 出现在错误的位置,直到动画完成,然后立即跳转到正确的位置。任何的想法?我正在使用带有 Interface Builder 和 Constraints 的 Storyboards。 (3认同)
  • @evya当隐藏= NO时,仅适用于淡入淡出,不适用于淡出,隐藏= YES (2认同)

Mik*_*kin 113

淡出:

[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
}
Run Code Online (Sandbox Code Playgroud)

淡入淡出:

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
}
Run Code Online (Sandbox Code Playgroud)


Dha*_*u K 10

使用此解决方案获得平滑的淡出和淡入效果

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法就像

uielement.fadeIn()
uielement.fadeOut()
Run Code Online (Sandbox Code Playgroud)

谢谢


Mar*_*vie 9

我使用这个小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)
  }
}
Run Code Online (Sandbox Code Playgroud)


Moh*_*ari 8

快速 4.2

带扩展名:

extension UIView {
func hideWithAnimation(hidden: Bool) {
        UIView.transition(with: self, duration: 0.5, options: .transitionCrossDissolve, animations: {
            self.isHidden = hidden
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

简单的方法:

func setView(view: UIView, hidden: Bool) {
    UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
        view.isHidden = hidden
    })
}
Run Code Online (Sandbox Code Playgroud)


Sca*_*aux 7

斯威夫特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
     })
}
Run Code Online (Sandbox Code Playgroud)


小智 7

经过一些更改后,@Umair Afzal 的代码在 swift 5 中运行良好

 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)
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

用来

yourView.fadeOut()
yourView.fadeIn()
Run Code Online (Sandbox Code Playgroud)


Val*_*gin 6

UIView为此目的创建了类别,并实现了一个特殊的一点点不同的概念:visibility.我的解决方案的主要区别在于您可以在调用[view setVisible:NO animated:YES]之后立即同步检查[view visible]并获得正确的结果.这非常简单但非常有用.

此外,允许避免使用"否定布尔逻辑"(参见 代码完成,第269页,使用正布尔变量名称以获取更多信息).

迅速

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
    }

}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)


Tul*_*lon 5

Swift 5.0,带有泛型:

func hideViewWithAnimation<T: UIView>(shouldHidden: Bool, objView: T) {
    if shouldHidden == true {
        UIView.animate(withDuration: 0.3, animations: {
            objView.alpha = 0
        }) { (finished) in
            objView.isHidden = shouldHidden
        }
    } else {
        objView.alpha = 0
        objView.isHidden = shouldHidden
        UIView.animate(withDuration: 0.3) {
            objView.alpha = 1
        }
    }
}   
Run Code Online (Sandbox Code Playgroud)

使用:

hideViewWithAnimation(shouldHidden: shouldHidden, objView: itemCountLabelBGView)
hideViewWithAnimation(shouldHidden: shouldHidden, objView: itemCountLabel)
hideViewWithAnimation(shouldHidden: shouldHidden, objView: itemCountButton)
Run Code Online (Sandbox Code Playgroud)

这里itemCountLabelBGViewis a UIView, itemCountLabelis a UILabel& itemCountButtonis a UIButton,所以它适用于父类为 的每个视图对象UIView