概要:
很多时候,我们都可以看到一些应用,会在加载数据时,显示一个好看的占位动画。那么这个好看的占位动画是咋样实现的呢,这里给出了我自己的方案,仅供学习探讨。
先看效果图
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。
网友评论