ios UIView 隐藏/显示动画

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9115854/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 16:39:06  来源:igfitidea点击:

UIView Hide/Show with animation

iosobjective-cuiviewanimation

提问by JTApps

My simple goal is to fade animate hiding and showing functions.

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

Button.hidden = YES;

Simple enough. However, is it possible to have it fade out rather than just disappearing? It looks rather unprofessional that way.

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

回答by Nick Lockwood

In iOS 4 and later, there's a way to do this just using the UIView transition method without needing to import QuartzCore. You can just say:

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

Objective C

目标 C

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

Swift

迅速

UIView.transition(with: button, duration: 0.4, 
                  options: .transitionCrossDissolve, 
                  animations: {
                 button.hidden = false
              })

Previous Solution

以前的解决方案

Michail's solution will work, but it's not actually the best approach.

Michail 的解决方案会奏效,但实际上并不是最好的方法。

The problem with alpha fading is that sometimes the different overlapping view layers look weird as they fade out. There are some other alternatives using Core Animation. First include the QuartzCore framework in your app and add #import <QuartzCore/QuartzCore.h>to your header. Now you can do one of the following:

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

1) set button.layer.shouldRasterize = YES;and then use the alpha animation code that Michail provided in his answer. This will prevent the layers from blending weirdly, but has a slight performance penalty, and can make the button look blurry if it's not aligned exactly on a pixel boundary.

1) 设置button.layer.shouldRasterize = YES;然后使用 Michail 在他的回答中提供的 alpha 动画代码。这将防止图层奇怪地混合,但会造成轻微的性能损失,并且如果按钮未在像素边界上完全对齐,则会使按钮看起来模糊。

Alternatively:

或者:

2) Use the following code to animate the fade instead:

2) 使用以下代码为淡入淡出设置动画:

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

button.hidden = YES;

The nice thing about this approach is you can crossfade any property of the button even if they aren't animatable (e.g. the text or image of the button), just set up the transition and then set your properties immediately afterwards.

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

回答by evya

UIView animated properties are:

UIView 动画属性是:

- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch

Describe in: Animations

描述于: 动画

isHiddenis not one of them, so as I see it the best way is:

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

Swift 4:

斯威夫特 4:

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

Objective C:

目标 C:

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

回答by Mikhail Grebionkin

To fade out:

淡出:

Objective-C

目标-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

斯威夫特 2

UIView.animateWithDuration(0.3, animations: {
    button.alpha = 0
}) { (finished) in
    button.hidden = finished
}

Swift 3, 4, 5

斯威夫特 3、4、5

UIView.animate(withDuration: 0.3, animations: {
    button.alpha = 0
}) { (finished) in
    button.isHidden = finished
}

To fade in:

淡入:

Objective-C

目标-C

button.alpha = 0;
button.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
    button.alpha = 1;
}];

Swift 2

斯威夫特 2

button.alpha = 0
button.hidden = false
UIView.animateWithDuration(0.3) {
    button.alpha = 1
}

Swift 3, 4, 5

斯威夫特 3、4、5

button.alpha = 0
button.isHidden = false
UIView.animate(withDuration: 0.3) {
    button.alpha = 1
}

回答by Mark Mckelvie

I use this little Swift 3extension:

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

回答by Mohsen mokhtari

swift 4.2

快速 4.2

with extension :

带扩展名:

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

simple method:

简单的方法:

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

回答by Scaraux

Swift 3

斯威夫特 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
     })
}

回答by Dhanu K

Use this solution for a smooth fadeOut and fadeIn effects

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

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

usage is as like

用法就像

uielement.fadeIn()
uielement.fadeOut()

Thanks

谢谢

回答by Valentin Shergin

I created category for UIViewfor this purpose and implemented a special little bit different concept: visibility. The main difference of my solution is that you can call [view setVisible:NO animated:YES]and right after that synchronously check [view visible]and get correct result. This is pretty simple but extremely useful.

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

Besides, it is allowed to avoid using "negative boolean logic" (see Code Complete, page 269, Use positive boolean variable namesfor more information).

此外,允许避免使用“负布尔逻辑”(有关详细信息,请参阅 代码完成,第 269 页,使用正布尔变量名称)。

Swift

迅速

UIView+Visibility.swift

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

目标-C

UIView+Visibility.h

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

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

回答by Sanjay Mishra

the code of @Umair Afzal working fine in swift 5 after some changes

经过一些更改后,@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)
    }
  }
}

for use

用来

yourView.fadeOut()
yourView.fadeIn()

回答by Umair Afzal

Swift 4

斯威夫特 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)
    }
}
}

And to use use it, simple call these functions like:

并使用它,简单地调用这些函数,如:

yourView.fadeOut() // this will hide your view with animation
yourView.fadeIn() /// this will show your view with animation