一般来说,我们的项目中请求网络数据是一个比较耗时的操作,在请求的过程中如果给用户只展示空白的页面或者默认的页面,难免显得有些单调,这个时候我们可以添加一个指示动画,开始请求的时候运行动画,数据请求下来了停止动画,这样用户体验会好一些。下面开始自定义我们自己的加载指示动画。
做好之后的效果图如下
使用Xcode新建一个工程 ,我们选择singleView,给工程取名字我这边叫MYLoadingView。然后我们进入工程所在文件夹创建一个文件夹取名为MYAninationView,把 该文件夹拖进我们的工程,记住勾选 copyItemIfNeed。
完成之后是下面这个样子,
在MYLoadingAnimation文件夹下创建自定义动画视图类,取名为MYLoadingAnimationView,继承于UIView。
然后我们就可以在这个类里面写我们的动画了。
在.h中添加一个初始化方法 、一个开始动画的方法、一个停止动画的方法。
这个 type是我们的动画类型,我们可以根据类型创建不同的动画效果,类型枚举 如下
这里我们只写一种作为示范,在.m里面我们写我们的动画实现。源代码如下,这里只写了一种效果,没有进行类型判断,我们也可以根据自己的兴趣创建自己想要的动画效果,这里使用的是 关键帧动画,
#import "MYLoadingAnimationView.h"
// 小球默认高度
static constCGFloat defauleSize = 40.0f;
@implementation MYLoadingAnimationView
-(id)initWithSize:(CGFloat)size type:(MYLoadingAnimtaionType)animationType
{
if (self = [superinit]) {
_animationType = animationType;
_viewSize = size;
}
return self;
}
- (void)startAnimation
{
if (!self.layer.sublayers) {
[selfsetupAnimationLayer];
}
self.layer.speed =1.0f;
_isAnimating = YES;
}
- (void)stopAnimation
{
self.layer.speed =0.0f;
_isAnimating = NO;
}
- (void)setupAnimationLayer
{
CALayer *layer = self.layer;
//子layer置空,加载新的
self.layer.sublayers =nil;
NSTimeInterval beginTime = CACurrentMediaTime();
CGFloat oX = (layer.bounds.size.width -_viewSize) / 2.0f;
CGFloat oY = (layer.bounds.size.height -_viewSize) / 2.0f;
for (int i =0; i < 2; i++) {
CALayer *circle = [CALayerlayer];
circle.frame = CGRectMake(oX, oY, defauleSize, defauleSize);
circle.anchorPoint = CGPointMake(0.5f, 0.5f);
circle.opacity = 0.5f;
circle.cornerRadius = defauleSize / 2.0f;
circle.transform = CATransform3DMakeScale(0.0f, 0.0f, 0.0f);
circle.backgroundColor = [UIColorredColor].CGColor;
//关键帧动画
CAKeyframeAnimation *transformAnimation = [CAKeyframeAnimationanimationWithKeyPath:@"transform"];
transformAnimation.removedOnCompletion =NO;
transformAnimation.repeatCount = HUGE_VALF;
transformAnimation.duration = 2.0f;
transformAnimation.beginTime = beginTime - (1.0f * i);
transformAnimation.keyTimes = @[@(0.0f), @(0.5f), @(1.0f)];
transformAnimation.timingFunctions =@[[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut],
[CAMediaTimingFunctionfunctionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
transformAnimation.values =@[[NSValuevalueWithCATransform3D:CATransform3DMakeScale(0.0f,0.0f, 0.0f)],
[NSValuevalueWithCATransform3D:CATransform3DMakeScale(1.0f,1.0f, 0.0f)],
[NSValuevalueWithCATransform3D:CATransform3DMakeScale(0.0f,0.0f, 0.0f)]];
[layer addSublayer:circle];
[circle addAnimation:transformAnimationforKey:@"animation"];
}
}
#pragma -mark setter
- (void)setViewSize:(CGFloat)viewSize
{
if (_viewSize != viewSize) {
_viewSize = viewSize;
}
}
@end
自定义动画类完成之后我们就可以在我们的视图控制器中使用了,我们给试图控制器添加两个按钮一个开始,一个停止,点击事件分别如下。
#import "ViewController.h"
#import "MYLoadingAnimationView.h"
@interface ViewController ()
{
MYLoadingAnimationView *_loadingView;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
MYLoadingAnimationView *view = [[MYLoadingAnimationViewalloc]initWithSize:40.0ftype:MYLoadingAnimtaionTypeDoubleBall];
view.frame = CGRectMake(0,0, 80,80);
view.center = self.view.center;
[self.viewaddSubview:view];
_loadingView = view;
}
- (IBAction)start {
[_loadingViewstartAnimation];
}
- (IBAction)stop:(id)sender {
[_loadingViewstopAnimation];
}
- (void)didReceiveMemoryWarning {
[superdidReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
效果如下
我们可以进一步封装,把创建不同动画的过程封装起来,我们的动画View 初始化的时候 根据不同的 类型调用不同的动画,就能够实现多种类型了。