Answers:
在iOS 4及更高版本中,有一种方法可以仅使用UIView过渡方法来执行此操作,而无需导入QuartzCore。您可以说:
[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
})
Michail的解决方案会起作用,但实际上并不是最佳方法。
Alpha淡入的问题在于,有时不同的重叠视图层在淡出时看起来很奇怪。还有一些使用Core Animation的替代方法。首先在您的应用程序中包含QuartzCore框架,并将其添加#import <QuartzCore/QuartzCore.h>
到标题中。现在,您可以执行以下操作之一:
1)设置button.layer.shouldRasterize = YES;
然后使用Michail在其答案中提供的alpha动画代码。这样可以防止各层怪异地融合在一起,但会降低性能,并且如果按钮未完全在像素边界上对齐,则可能会使按钮显得模糊。
或者:
2)改用以下代码设置淡入淡出的动画效果:
CATransition *animation = [CATransition animation];
animation.type = kCATransitionFade;
animation.duration = 0.4;
[button.layer addAnimation:animation forKey:nil];
button.hidden = YES;
这种方法的好处是,即使按钮无法设置动画(例如按钮的文本或图像),您也可以对其进行淡入淡出处理,只需设置过渡,然后立即设置属性即可。
transitionWithView
参数,以确保成功淡入和淡出。
UIView动画属性是:
- frame
- bounds
- center
- transform
- alpha
- backgroundColor
- contentStretch
描述: 动画
isHidden
不是其中之一,因此我认为最好的方法是:
斯威夫特4:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
目标C:
- (void)setView:(UIView*)view hidden:(BOOL)hidden {
[UIView transitionWithView:view duration:0.5 options:UIViewAnimationOptionTransitionCrossDissolve animations:^(void){
[view setHidden:hidden];
} completion:nil];
}
淡出:
目标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*)
}];
迅捷2
UIView.animateWithDuration(0.3, animations: {
button.alpha = 0
}) { (finished) in
button.hidden = finished
}
斯威夫特3,4,5
UIView.animate(withDuration: 0.3, animations: {
button.alpha = 0
}) { (finished) in
button.isHidden = finished
}
淡入:
目标C
button.alpha = 0;
button.hidden = NO;
[UIView animateWithDuration:0.3 animations:^{
button.alpha = 1;
}];
迅捷2
button.alpha = 0
button.hidden = false
UIView.animateWithDuration(0.3) {
button.alpha = 1
}
斯威夫特3,4,5
button.alpha = 0
button.isHidden = false
UIView.animate(withDuration: 0.3) {
button.alpha = 1
}
我使用这个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)
}
}
迅捷4.2
带有扩展名:
extension UIView {
func hideWithAnimation(hidden: Bool) {
UIView.transition(with: self, duration: 0.5, options: .transitionCrossDissolve, animations: {
self.isHidden = hidden
})
}
}
简单方法:
func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: {
view.isHidden = hidden
})
}
使用此解决方案可获得平滑的淡出和淡入效果
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)
}
}
用法就像
uielement.fadeIn()
uielement.fadeOut()
谢谢
fadeOut
仅当我删除设置的行时,才能在iOS 13上运行self.isHidden
。
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
}
}
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
经过一些更改后,@ 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)
}
}
}
用来
yourView.fadeOut()
yourView.fadeIn()
斯威夫特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)
}
}
}
要使用它,只需调用以下函数即可:
yourView.fadeOut() // this will hide your view with animation
yourView.fadeIn() /// this will show your view with animation
您可以使用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
})
}
你可以试试看
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)
})
}
并传递您的视图名称
showView(objView: self.viewSaveCard)
HideView(objView: self.viewSaveCard)
如果您的视图默认情况下设为“隐藏”,或者您更改了“隐藏”状态(我认为在很多情况下应该这样做),那么此页面中的任何一种方法都不会同时为您提供FadeIn / FadeOut动画,它只会为其中一种状态设置动画,原因是您在调用UIView.animate之前将Hidden状态设置为false方法这将导致突然的可见性;如果仅对Alpha进行动画处理,则对象空间仍然存在,但是不可见,这将导致某些UI问题。
因此,最好的方法是先检查视图是否被隐藏,然后将alpha设置为0.0,这样将Hidden状态设置为false时,您将不会看到可见的图像。
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(with :)函数非常简洁。
许多人都发布了它,但没有人注意到只有在运行它时才会出现故障。
您可以将隐藏属性完美地转换为true,而当您尝试将其转换为false时,视图将突然消失而没有任何动画。
这是因为此api仅在视图中起作用,这意味着当您转换视图以显示(实际上本身会立即显示)时,仅其内容会逐渐动画。
当您尝试隐藏此视图时,其本身会立即隐藏,从而使动画内容无意义。
为了解决这个问题,在隐藏视图时,过渡目标应该是其父视图,而不是要隐藏的视图。
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)
}
我对Swift 3的解决方案。因此,我创建了一个函数,该函数以正确的顺序隐藏/取消隐藏视图(隐藏时-将alpha设置为0,然后将isHidden设置为true;取消隐藏-首先显示视图,然后将其alpha设置为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
块中有另一个动画hide
是false?
迅捷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)?'
有用的参考。
isHidden
值将立即呈现(即,立即隐藏/显示视图)。
这段代码给出了一个动画,就像在uinavigation controller中推送viewController一样。
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromRight;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = true;
用于流行动画...
CATransition *animation = [CATransition animation];
animation.type = kCATransitionPush;
animation.subtype = kCATransitionFromLeft;
animation.duration = 0.3;
[_viewAccountName.layer addAnimation:animation forKey:nil];
_viewAccountName.hidden = false;
尝试了一些已存在的答案,一些仅在一种情况下有效,其中一些需要添加两个功能。
选项1
与无关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
})
}
}
然后通过isFadeIn
(true
或false
)
view.animate(fadeIn: isFadeIn)
选项2
不要传递任何参数。根据淡入或淡出isUserInteractionEnabled
。这也非常适合来回动画的情况。
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
})
}
然后你打电话
yourView.animateFadeInOut()
为什么
self.isUserInteractionEnabled
呢试图替换
self.isUserInteractionEnabled
为self.isHidden
,根本没有运气。
而已。花了我一些时间,希望它能帮助别人。