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