iOS开发 ---封装一个加载动画类

2022-05-30  本文已影响0人  我是卖报的小行家

(需要结合MBProgressHUD一起使用)新建一个类

+(instancetype)showLoading; //显示
+(void)showLoadingText:(NSString *)text delay:(NSInteger)delay;
+(void)hideLoading;  //隐藏
+(void)toast:(NSString *)text;
#import "ZKLoadingView.h"
#import "MBProgressHUD.h"
//球宽高
static CGFloat BallWidth = 12.0f;
//球速
static CGFloat BallSpeed = 0.7f;
//球缩放比例
static CGFloat BallZoomScale = 0.25;
//暂停时间
static CGFloat PauseSecond = 0.18;


typedef NS_ENUM(NSInteger,BallMoveDirection){
    BallMoveDirectionPositive = 1,
    BallMoveDirectionNegative = -1
};


@interface ZKLoadingView ()
@property (nonatomic, strong) UIView * Bg;
//球的容器
@property (nonatomic, strong) UIView *ballContainer;
//绿球
@property (nonatomic, strong) UIView *greenBall;
//红球
@property (nonatomic, strong) UIView *redBall;
//黑球
@property (nonatomic, strong) UIView *blackBall;
//移动方向
@property (nonatomic, assign) BallMoveDirection ballMoveDirection;
//刷新器
@property (nonatomic, strong) CADisplayLink *displayLink;
@property (nonatomic, assign) BOOL bRegister;
//开始动画
- (void)startAnimated;
//停止动画
- (void)stopAnimated;
@end

@implementation ZKLoadingView

+ (instancetype)showLoading
{
    [self hideLoading];
    UIView *view = [UIApplication sharedApplication].windows[0];
    ZKLoadingView *loading = [[ZKLoadingView alloc]initWithFrame:view.bounds];
    [view addSubview:loading];
    [loading startAnimated];
    return loading;
}


+ (void)hideLoading
{
    UIView *view = [UIApplication sharedApplication].windows[0];
    NSEnumerator *subViewsEnum = [view.subviews reverseObjectEnumerator]; //逆向遍历
    for (UIView *subViews in subViewsEnum) {
        if ([subViews isKindOfClass:self]) {
            ZKLoadingView *loading = (ZKLoadingView *)subViews;
            [loading stopAnimated];
            if (loading.displayLink) {
                [loading.displayLink invalidate];
                loading.displayLink = nil;
                loading.bRegister = NO;
            }
            [loading removeFromSuperview];
            return;
        }
    }
    
    
    
}

+ (void)showLoadingText:(NSString *)text delay:(NSInteger)delay
{
    MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:[UIApplication sharedApplication].windows[0] animated:YES];
    hud.contentColor = [UIColor whiteColor];
    hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
    hud.bezelView.color = UIColor.systemPinkColor;
    hud.mode = MBProgressHUDModeText;
    hud.label.text = text;
    hud.label.numberOfLines = 0;
    [hud hideAnimated:YES afterDelay:delay];
}

+ (void)toast:(NSString *)text
{
    [ZKLoadingView showLoadingText:text delay:1];
}

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
        [self createUI];
    }
    return self;
}

-(void)createUI{
   
    self.Bg = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 88, 88)];
    self.Bg.backgroundColor = UIColor.systemGrayColor;
    self.Bg.center = [self center];
    self.Bg.layer.cornerRadius = 8;
    self.Bg.layer.masksToBounds = YES;
    [self addSubview:self.Bg];
    
    self.ballContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 2.1*BallWidth, 2*BallWidth)];
    self.ballContainer.center = [self center];
    [self addSubview:self.ballContainer];
    
    self.greenBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, BallWidth, BallWidth)];
    self.greenBall.center = CGPointMake(BallWidth/2.0f, self.ballContainer.bounds.size.height/2.0f);
    self.greenBall.layer.cornerRadius = BallWidth/2.0f;
    self.greenBall.layer.masksToBounds = true;
    self.greenBall.backgroundColor = [UIColor colorWithRed:35/255.0f green:246/255.0f blue:235/255.0f alpha:1];
    [self.ballContainer addSubview:self.greenBall];
    
    self.redBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, BallWidth, BallWidth)];
    self.redBall.center = CGPointMake(self.ballContainer.bounds.size.width - BallWidth/2.0f, self.ballContainer.bounds.size.height/2.0f);
    self.redBall.layer.cornerRadius = BallWidth/2.0f;
    self.redBall.layer.masksToBounds = true;
    self.redBall.backgroundColor = [UIColor colorWithRed:255/255.0f green:46/255.0f blue:86/255.0f alpha:1];
    [self.ballContainer addSubview:self.redBall];
    
    //第一次动画是正向,绿球在上,红球在下,阴影会显示在绿球上
    self.blackBall = [[UIView alloc] initWithFrame:CGRectMake(0, 0, BallWidth, BallWidth)];
    self.blackBall.backgroundColor = [UIColor colorWithRed:12/255.0f green:11/255.0f blue:17/255.0f alpha:1];
    self.blackBall.layer.cornerRadius = BallWidth/2.0f;
    self.blackBall.layer.masksToBounds = true;
    [self.greenBall addSubview:self.blackBall];
    
    //初始化方向是正向
    self.ballMoveDirection = BallMoveDirectionPositive;
    self.bRegister = NO;
    //初始化刷新方法
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateBallAnimations)];
}


- (void)startAnimated
{
    if (!self.bRegister) {
        [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
        self.bRegister = YES;
    }
}

- (void)stopAnimated
{
    if (self.bRegister) {
        [self.displayLink removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
        self.bRegister = NO;
    }
}

- (void)pauseAnimated {
    [self stopAnimated];
    dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(PauseSecond*NSEC_PER_SEC));
    dispatch_after(delayTime, dispatch_get_main_queue(), ^{
        [self startAnimated];
    });
}


- (void)updateBallAnimations {
    if (self.ballMoveDirection == BallMoveDirectionPositive) {//正向运动
        //更新绿球位置
        CGPoint center = self.greenBall.center;
        center.x += BallSpeed;
        self.greenBall.center = center;
        
        //更新红球位置
        center = self.redBall.center;
        center.x -= BallSpeed;
        self.redBall.center = center;
        
        //缩放动画,绿球放大 红球变小
        self.greenBall.transform = [self ballLargerTransformOfCenterX:center.x];
        self.redBall.transform = [self ballSmallerTransformOfCenterX:center.x];
        
        //更新黑球位置
        CGRect blackBallFrame = [self.redBall convertRect:self.redBall.bounds toCoordinateSpace:self.greenBall];
        self.blackBall.frame = blackBallFrame;
        self.blackBall.layer.cornerRadius = self.blackBall.bounds.size.width/2.0f;
        
        //更新方向+改变三个球的相对位置
        if (CGRectGetMaxX(self.greenBall.frame) >= self.ballContainer.bounds.size.width || CGRectGetMinX(self.redBall.frame) <= 0) {
            //切换为反向
            self.ballMoveDirection = BallMoveDirectionNegative;
            //反向运动时,红球在上,绿球在下
            [self.ballContainer bringSubviewToFront:self.redBall];
            //黑球放在红球上面
            [self.redBall addSubview:self.blackBall];
            //暂停一下
            [self pauseAnimated];
        }
    }else if (self.ballMoveDirection == BallMoveDirectionNegative) {//反向运动
        //更新绿球位置
        CGPoint center = self.greenBall.center;
        center.x -= BallSpeed;
        self.greenBall.center = center;
        
        //更新红球位置
        center = self.redBall.center;
        center.x += BallSpeed;
        self.redBall.center = center;
        
        //缩放动画,红球放大 绿/黑球变小
        self.redBall.transform = [self ballLargerTransformOfCenterX:center.x];
        self.greenBall.transform = [self ballSmallerTransformOfCenterX:center.x];
        
        //更新黑球位置
        CGRect blackBallFrame = [self.greenBall convertRect:self.greenBall.bounds toCoordinateSpace:self.redBall];
        self.blackBall.frame = blackBallFrame;
        self.blackBall.layer.cornerRadius = self.blackBall.bounds.size.width/2.0f;
        
        //更新方向+改变三个球的相对位置
        if (CGRectGetMinX(self.greenBall.frame) <= 0 || CGRectGetMaxX(self.redBall.frame) >= self.ballContainer.bounds.size.width) {
            //切换为正向
            self.ballMoveDirection = BallMoveDirectionPositive;
            //正向运动时,绿球在上,红球在下
            [self.ballContainer bringSubviewToFront:self.greenBall];
            //黑球放在绿球上面
            [self.greenBall addSubview:self.blackBall];
            //暂停动画
            [self pauseAnimated];
        }
    }
}


//放大动画
- (CGAffineTransform)ballLargerTransformOfCenterX:(CGFloat)centerX {
    CGFloat cosValue = [self cosValueOfCenterX:centerX];
    return CGAffineTransformMakeScale(1 + cosValue*BallZoomScale, 1 + cosValue*BallZoomScale);
}

//缩小动画
- (CGAffineTransform)ballSmallerTransformOfCenterX:(CGFloat)centerX {
    CGFloat cosValue = [self cosValueOfCenterX:centerX];
    return CGAffineTransformMakeScale(1 - cosValue*BallZoomScale, 1 - cosValue*BallZoomScale);
}

//根据余弦函数获取变化区间 变化范围是0~1~0
- (CGFloat)cosValueOfCenterX:(CGFloat)centerX {
    CGFloat apart = centerX - self.ballContainer.bounds.size.width/2.0f;
    //最大距离(球心距离Container中心距离)
    CGFloat maxAppart = (self.ballContainer.bounds.size.width - BallWidth)/2.0f;
    //移动距离和最大距离的比例
    CGFloat angle = apart/maxAppart*M_PI_2;
    //获取比例对应余弦曲线的Y值
    return cos(angle);
}

@end

上一篇下一篇

猜你喜欢

热点阅读