利用CALayer實現動畫加載效果

BarLinsley 8年前發布 | 6K 次閱讀 CALayer iOS開發 移動開發

效果圖如下:

網上關于這種效果圖大多每一個圓圈都是使用UIView,因為這種容易控制,但是這里用的是CALayer.

控制器調用就一句代碼:

[self showLoadingInView:self.view];

方便控制器如此調用,就要為控制器添加一個分類

.h文件

#import <UIKit/UIKit.h>
#import "GQCircleLoadView.h"
@interface UIViewController (GQCircleLoad)
//顯示動畫
- (void)showLoadingInView:(UIView*)view;
//隱藏動畫
- (void)hideLoad;
@property (nonatomic,strong) GQCircleLoadView *loadingView;
@end

.m文件

#import "UIViewController+GQCircleLoad.h"
#import <objc/runtime.h>
@implementation UIViewController (GQCircleLoad)
- (GQCircleLoadView*)loadingView
{
    return objc_getAssociatedObject(self, @"loadingView");
}
- (void)setLoadingView:(GQCircleLoadView*)loadingView
{
    objc_setAssociatedObject(self, @"loadingView", loadingView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)showLoadingInView:(UIView*)view{
    if (self.loadingView == nil) {
        self.loadingView = [[GQCircleLoadView alloc]init];
    }
    if (view) {
        [view addSubview:self.loadingView];
        self.loadingView.frame = view.bounds;
    }else{
        UIWindow *appKeyWindow = [UIApplication sharedApplication].keyWindow;
        [appKeyWindow addSubview:self.loadingView];
        self.loadingView.frame = appKeyWindow.bounds;
    }
}
- (void)hideLoad{
    [self.loadingView removeFromSuperview];
}
@end

接下來就是GQCircleLoadView繼承UIView,里面通過drawRect畫出圓圈,并且動畫的實現

#import "GQCircleLoadView.h"
#define WINDOW_width  [[UIScreen mainScreen] bounds].size.width
#define WINDOW_height [[UIScreen mainScreen] bounds].size.height
static NSInteger circleCount = 3;
static CGFloat cornerRadius = 10;
static CGFloat magin = 15;
@interface GQCircleLoadView()<CAAnimationDelegate>
@property (nonatomic, strong) NSMutableArray *layerArr;
@end

@implementation GQCircleLoadView
- (instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}
// 畫圓
- (void)drawCircles{
    for (NSInteger i = 0; i < circleCount; ++i) {
        CGFloat x = (WINDOW_width - (cornerRadius*2) * circleCount - magin * (circleCount-1)) / 2.0 + i * (cornerRadius*2 + magin) + cornerRadius;
        CGRect rect = CGRectMake(-cornerRadius, -cornerRadius , 2*cornerRadius, 2*cornerRadius);
        UIBezierPath *beizPath=[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:cornerRadius];
        CAShapeLayer *layer=[CAShapeLayer layer];
        layer.path=beizPath.CGPath;
        layer.fillColor=[UIColor grayColor].CGColor;
        layer.position = CGPointMake(x, self.frame.size.height * 0.5);
        [self.layer addSublayer:layer];

        [self.layerArr addObject:layer];
    }

    [self drawAnimation:self.layerArr[0]];

    // 旋轉(可打開試試效果)
//    CABasicAnimation* rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
//    rotationAnimation.toValue = [NSNumber numberWithFloat: - M_PI * 2.0 ];
//    rotationAnimation.duration = 1;
//    rotationAnimation.cumulative = YES;
//    rotationAnimation.repeatCount = MAXFLOAT;
//    [self.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
}

// 動畫實現
- (void)drawAnimation:(CALayer*)layer {
    CABasicAnimation *scaleUp = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    scaleUp.fromValue = @1;
    scaleUp.toValue = @1.5;
    scaleUp.duration = 0.25;
    scaleUp.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    CABasicAnimation *scaleDown = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
    scaleDown.beginTime = scaleUp.duration;
    scaleDown.fromValue = @1.5;
    scaleDown.toValue = @1;
    scaleDown.duration = 0.25;
    scaleDown.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];

    CAAnimationGroup *group = [[CAAnimationGroup alloc] init];
    group.animations = @[scaleUp, scaleDown];
    group.repeatCount = 0;
    group.duration = scaleUp.duration + scaleDown.duration;
    group.delegate = self;
    [layer addAnimation:group forKey:@"groupAnimation"];

}
#pragma mark - CAAnimationDelegate
- (void)animationDidStart:(CAAnimation *)anim
{
    if ([anim isKindOfClass:CAAnimationGroup.class]) {
        CAAnimationGroup *animation = (CAAnimationGroup *)anim;

        [self.layerArr enumerateObjectsUsingBlock:^(CAShapeLayer *obj, NSUInteger idx, BOOL * _Nonnull stop) {

            CAAnimationGroup *a0 = (CAAnimationGroup *)[obj animationForKey:@"groupAnimation"];
            if (a0 && a0 == animation) {
                CAShapeLayer *nextlayer = self.layerArr[(idx+1)>=self.layerArr.count?0:(idx+1)];
                [self performSelector:@selector(drawAnimation:) withObject:nextlayer afterDelay:0.25];
                *stop = YES;
            }
        }];
    }
}
- (void)drawRect:(CGRect)rect{
    [super drawRect:rect];
    [self drawCircles];
}
- (NSMutableArray *)layerArr{
    if (_layerArr == nil) {
        _layerArr = [[NSMutableArray alloc] init];
    }
    return _layerArr;
}
@end

Demo就不上傳了,總共四個文件代碼已經全貼上了!

打開上面的旋轉的動畫代碼,關閉旋轉代碼,進一步修改也可實現出QQ郵箱的下拉刷新效果,有興趣可以試試.

 

 

來自:http://www.jianshu.com/p/b6ee57d25c7b

 

 本文由用戶 BarLinsley 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!