UIView动画隐藏子视图

25
我有一个名为EmptyCollectionView的UIView,在我的UICollectionView为空时显示。我是这样做的,我在我的ViewController的viewDidLoad中创建了这个UIView并addSubview,然后根据需要更改该视图的isHidden属性(以及collectionView)。
现在我想把它打磨得更好一些,我想为我的空视图中包含的子视图添加一些微妙的动画,比如在显示时使imageview弹跳。
所以我的问题是,检测UIView何时被显示是最好的方法是什么(即是否有可以使用的viewDidAppear类型回调函数)?
辅助问题:我是新手...将空视图添加和切换isHidden属性是一种好的方法吗?还是应该用不同的方式做?(即是否应该根据需要创建和销毁视图,而不是保留它)
谢谢

1
您可以通过动画修改UIView的约束或者透明度。 - JuicyFruit
5个回答

32

在我看来,最好的方法是扩展UIView。

extension UIView {
    
    func fadeIn(_ duration: TimeInterval = 0.2, onCompletion: (() -> Void)? = nil) {
        self.alpha = 0
        self.isHidden = false
        UIView.animate(withDuration: duration,
                       animations: { self.alpha = 1 },
                       completion: { (value: Bool) in
                          if let complete = onCompletion { complete() }
                       }
        )
    }
    
    func fadeOut(_ duration: TimeInterval = 0.2, onCompletion: (() -> Void)? = nil) {
        UIView.animate(withDuration: duration,
                       animations: { self.alpha = 0 },
                       completion: { (value: Bool) in
                           self.isHidden = true
                           if let complete = onCompletion { complete() }
                       }
        )
    }
    
}

所以,你只需要调用view.fadeIn()来进行默认的0.2秒动画,或者调用view.fadeIn(1)使其持续一秒钟。

你甚至可以添加完成事件:

view.fadeOut(0.5, onCompletion: {
    print("Animation completed, do whatever you want")
})

这是一个非常聪明的解决方案。 - Burak Akyalçın
然而,与其使用"if let complete = onCompletion { complete() }",不如直接使用"complete?()"。问号可以在没有if语句的情况下测试是否为nil。 - clearlight

17

Swift 4.2 的扩展,允许在任何 UIView 类上设置 isHidden 属性时执行动画:

extension UIView {
    func setIsHidden(_ hidden: Bool, animated: Bool) {
        if animated {
            if self.isHidden && !hidden {
                self.alpha = 0.0
                self.isHidden = false
            }
            UIView.animate(withDuration: 0.25, animations: {
                self.alpha = hidden ? 0.0 : 1.0
            }) { (complete) in
                self.isHidden = hidden
            }
        } else {
            self.isHidden = hidden
        }
    }
}

17

这个方法有效,希望能够帮到你。要隐藏视图:

UIView.animate(withDuration: 0.3/*Animation Duration second*/, animations: {
     self.EmptyCollectionView.alpha = 0
}, completion:  {
   (value: Bool) in
       self.EmptyCollectionView.isHidden = true
})
展示视图:

展示视图:

self.EmptyCollectionView.isHidden = false
UIView.animate(withDuration: 0.3, animations: {
         self.EmptyCollectionView.alpha = 1
    }, completion:  nil)

请问在 ShowView 完成时:为什么您没有将 .isHidden 再次设置为 false 呢? - Let.Simoo

3
您可以将EmptyCollectionView的alpha属性动画化为0以隐藏或1以显示。
UIView.animate(withDuration: 0.5) { 
    self.EmptyCollectionView.alpha = 0
}

还要确保将isOpaque属性设置为False,以启用视图的透明度


但我想要动画化子视图而不是视图本身。我的emptyview包含一个imageview,当emptyview显示或隐藏时,我想要动画化这个imageview。我通过添加一个show和hide函数来解决了这个问题,该函数设置self.isHidden并执行动画。有点烦人,因为现在一些视图使用isHidden = false,而其他视图使用view.show(),看起来有点凌乱,但目前它可以工作。 - TRG

1

Swift 5

import UIKit

extension UIView {
    
    func animateSetHidden(_ hidden: Bool, duration: CGFloat = CATransaction.animationDuration(), completion: @escaping (Bool)->() = { _ in}) {
        
        if duration > 0 {

            if self.isHidden && !hidden {
                self.alpha = 0
                self.isHidden = false
            } 
            UIView.animate(withDuration: duration, delay:0, options: .beginFromCurrentState) {
            
                self.alpha = hidden ? 0 : 1
            
            } completion: { c in
          
                if c {
                    self.isHidden = hidden
                }
                completion(c)
            
            }

        } else {
            
            self.isHidden = hidden
            self.alpha = hidden ? 0 : 1
            completion(true)

        }
        
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接