程序员效果

Swift4.0--弱网时,酷炫的占位动画实现思路详解

2018-04-11  本文已影响111人  青苹果园
loading.jpeg

概要:

很多时候,我们都可以看到一些应用,会在加载数据时,显示一个好看的占位动画。那么这个好看的占位动画是咋样实现的呢,这里给出了我自己的方案,仅供学习探讨。

先看效果图

windlessGif1

实现思路

一、首先我们根据设计图布局视图,为view(cell)中的每一个子空间设置约束,特别注意的是控件的宽度是必须限制的(给固定值或左右约束);

二、再为刚才视图中的每一个子控件覆盖一层弱网视图view(这里称它windlessView),并为windlessView添加动画,效果如图;这一步我直接为UIView添加了一个扩展方法,凡是继承view的都可调用;

三、在下拉加载数据之前,我们已经把一屏幕的view(cell)都创建好并显示(即带弱网效果的视图),当我们的数据返回时,重新刷新界面,并移除windlessView。

注意:

  • 在我的项目中使用的是MVVM框架,所以我在ViewModel中添加了一个isWindless的属性,加载数据时,默认为true显示弱网效果,当数据成功返回时,值设为false,移除windlessView。

  • 弱网状态禁止交互。

添加弱网效果的核心代码如下:

为当前view添加弱网视图和动画

import UIKit

let kWindlessViewTag = 91997

extension UIView {
    /// 为视图添加弱网效果
    ///
    /// - Parameter isWindless: 是否为弱网状态
    func windless(isWindless: Bool) {
        var windLessView: UIView? = self.viewWithTag(kWindlessViewTag)
        if isWindless {
            if windLessView == nil {
                // 添加弱网视图
                windLessView = UIView(frame: self.bounds)
                windLessView!.backgroundColor = UIColor(red: 247.0/255.0, green: 247.0/255.0, blue: 247.0/255.0, alpha: 1.0)
                windLessView?.layer.position    = CGPoint(x: 0, y: 0)
                windLessView?.layer.anchorPoint = CGPoint(x: 0, y: 0)
                windLessView!.tag = kWindlessViewTag
                self.addSubview(windLessView!)
            }
            // 添加动画
            let random = CGFloat(self.randomNum(start: 4, end: 6)) / 10.0
            let minW = self.bounds.size.width * random
            let maxW = self.bounds.size.width * 1.0
            let animation = CABasicAnimation(keyPath: "bounds.size.width")
            animation.duration      = 1
            animation.repeatCount   = MAXFLOAT
            animation.autoreverses  = true
            animation.fromValue     = CGFloat(minW)
            animation.toValue       = CGFloat(maxW)
            animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
            windLessView!.layer.add(animation, forKey: "WindlessAnimation")
            
        } else {
            guard windLessView != nil else {
                return
            }
            // 移除弱网视图
            windLessView?.removeFromSuperview()
        }
    }

    /// 获取(start~end)的随机数(为了让动画更好看)
    func randomNum(start: Int, end: Int) -> Int {
        var temp = Int(arc4random_uniform(UInt32(end))) + 1
        if temp < start {
            temp = self.randomNum(start: start, end: end)
        }
        return temp
    }
}

案例:

下面是我重写setupContent为基类方法,刷新某个cell的数据,cell的显示样式根据ViewModel的具体值来展示。

override func setupContent<T>(model: T) where T: HomeResearchInfoViewModel {
        updateContenView(isWindless: model.isWindless)
        isUserInteractionEnabled = !model.isWindless
        guard !model.isWindless else {
            return
        }
        // TODO: 根据数据更新视图。。。
    }

    func updateContenView(isWindless: Bool) {
        titleLabel.windless(isWindless: isWindless)
        detailLabel.windless(isWindless: isWindless)
    }

最后来一张完整的效果图

windlessGif

这里没有再提供demo。

这是我的GitHub欢迎交流学习

上一篇下一篇

猜你喜欢

热点阅读