分三段动画
第一段pulling动画
手动打开书本,跟随下拉手势距离修改动画播放百分比。
第二段文字跳出
刷新过程中文字跳到出现动效,只播放一次,播放完成后,一直保留到完全结束刷新。
第三段持续翻书动效
刷新过程中,书本翻动动效,可持续轮播或播放一次动画后,自动完成刷新。
上代码:
#import "MJRefreshHeader.h"
NS_ASSUME_NONNULL_BEGIN
@interface DDRefreshLottieHeader : MJRefreshHeader
@property (nonatomic, assign) BOOL isAutoEndRefreshing; //!< 翻书动效执行一遍后自动收起
@property (nonatomic, assign) BOOL isNeedMoveToTop; //!<设置ignoredScrollViewContentInsetTop后,为了避免被遮挡 是否需要将刷新控件移到最顶部
/// 模拟手动下拉刷新
/// @param refreshHeader refreshHeader
+ (void)beginLottiePullingRefreshing:(MJRefreshHeader *)refreshHeader;
@end
NS_ASSUME_NONNULL_END
#import "DDRefreshLottieHeader.h"
#import "DDLottieAnimationView.h"
static const CGFloat LottieHeader_loading_originY = 6.0;
static const CGFloat LottieHeader_loading_width = 90.0;
static const CGFloat LottieHeader_loading_height = 65.0;
@interface DDRefreshLottieHeader()
@property (nonatomic, strong) DDLottieAnimationView *pullingLottieView;
@property (nonatomic, strong) DDLottieAnimationView *refreshTextLottieView;
@property (nonatomic, strong) DDLottieAnimationView *refreshLoopLottieView;
@property (nonatomic, assign) BOOL isRefreshing;
@end
@implementation DDRefreshLottieHeader
#pragma mark - 重写方法
//TODO: 在这里做一些初始化配置(比如添加子控件)
- (void)prepare
{
[super prepare];
self.layer.zPosition = -1;
self.mj_h = LottieHeader_loading_height + 8;
}
//TODO: 在这里设置子控件的位置和尺寸
- (void)placeSubviews
{
[super placeSubviews];
[self addSubview:self.refreshTextLottieView];
[self addSubview:self.pullingLottieView];
[self addSubview:self.refreshLoopLottieView];
}
- (void)setIsAutoEndRefreshing:(BOOL)isAutoEndRefreshing
{
self.refreshLoopLottieView.loopAnimation = NO;
}
- (void)setIsNeedMoveToTop:(BOOL)isNeedMoveToTop
{
_isNeedMoveToTop = isNeedMoveToTop;
}
#pragma mark 模拟下拉刷新状态
+ (void)beginLottiePullingRefreshing:(DDRefreshLottieHeader *)refreshHeader
{
refreshHeader.pullingPercent = 0.0;
[UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
refreshHeader.alpha = 1.0;
refreshHeader.pullingPercent = 1.0;
} completion:^(BOOL finished) {
[refreshHeader beginRefreshing];
}];
}
#pragma mark- 监听拖拽比例(控件被拖出来的比例)
- (void)setPullingPercent:(CGFloat)pullingPercent
{
if (self.isNeedMoveToTop) {
self.layer.zPosition = 1024;
}
if (pullingPercent <= 0.05) {
return;
}
if ( self.isRefreshing || pullingPercent >= 1.0) {
self.pullingLottieView.hidden = YES;
self.refreshLoopLottieView.hidden = NO;
return;
}
self.pullingLottieView.hidden = NO;
self.refreshLoopLottieView.hidden = YES;
[super setPullingPercent:pullingPercent];
CGFloat progressBegin = pullingPercent - 1.0 >= 0 ? 1.0 : pullingPercent;
self.pullingLottieView.animationProgress = progressBegin;
}
#pragma mark - 监听控件的刷新状态 根据状态做事情
- (void)setState:(MJRefreshState)state
{
self.isRefreshing = NO;
MJRefreshCheckState;
switch (state) {
case MJRefreshStatePulling: {
//下拉状态: 监听拖拽比例设置动画效果(控件被拖出来的比例)
}
break;
case MJRefreshStateRefreshing: {
//刷新状态
self.isRefreshing = YES;
self.pullingLottieView.hidden = YES;
self.refreshLoopLottieView.animationProgress = 0.0;
[self.refreshTextLottieView play];
self.refreshLoopLottieView.hidden = NO;
if (self.isAutoEndRefreshing) {
[self autoEndRefreshing];
} else {
[self.refreshLoopLottieView play];
}
break;
}
default: {
if (self.isAutoEndRefreshing) {
[self autoEndRefreshing];
weakify(self);
self.endRefreshingCompletionBlock = ^{
strongify(self);
if (self.isNeedMoveToTop) {
self.layer.zPosition = -1;
}
};
} else {
weakify(self);
[self.refreshLoopLottieView pause];
self.endRefreshingCompletionBlock = ^{
strongify(self);
[self initLottieAnimationProgress];
if (self.isNeedMoveToTop) {
self.layer.zPosition = -1;
}
};
}
}
break;
}
}
- (void)autoEndRefreshing
{
weakify(self);
[self.refreshLoopLottieView playToProgress:0.9 withCompletion:^(BOOL animationFinished) {
strongify(self);
[self endRefreshing];
}];
}
- (void)initLottieAnimationProgress
{
//初始状态
[self.pullingLottieView stop];
[self.refreshTextLottieView stop];
[self.refreshLoopLottieView pause];
self.pullingLottieView.hidden = NO;
self.refreshLoopLottieView.hidden = YES;
}
- (DDLottieAnimationView *)refreshTextLottieView
{
if (_refreshTextLottieView == nil) {
_refreshTextLottieView = [DDLottieAnimationView animationNamed:app_lottie_refresh_slogan_json];
_refreshTextLottieView.frame = CGRectMake((DD_SCREEN_WIDTH - LottieHeader_loading_width) * 0.5,LottieHeader_loading_originY, LottieHeader_loading_width, LottieHeader_loading_height);
_refreshTextLottieView.loopAnimation = NO;
}
return _refreshTextLottieView;
}
- (DDLottieAnimationView *)pullingLottieView
{
if (_pullingLottieView == nil) {
_pullingLottieView = [DDLottieAnimationView animationNamed:app_lottie_refresh_book_open_json];
_pullingLottieView.frame = CGRectMake((DD_SCREEN_WIDTH - LottieHeader_loading_width) * 0.5, LottieHeader_loading_originY, LottieHeader_loading_width, LottieHeader_loading_height);
_pullingLottieView.loopAnimation = NO;
}
return _pullingLottieView;
}
- (DDLottieAnimationView *)refreshLoopLottieView
{
if (_refreshLoopLottieView == nil) {
_refreshLoopLottieView = [DDLottieAnimationView animationNamed:app_lottie_refresh_book_flip_json];
_refreshLoopLottieView.frame = CGRectMake((DD_SCREEN_WIDTH - LottieHeader_loading_width) * 0.5, LottieHeader_loading_originY, LottieHeader_loading_width, LottieHeader_loading_height);
_refreshLoopLottieView.loopAnimation = YES;
}
return _refreshLoopLottieView;
}
@end