美文网首页iOS DeveloperiOS之功能细节程序员
玩转MJRefresh下拉刷新自定义动画

玩转MJRefresh下拉刷新自定义动画

作者: LuisX | 来源:发表于2017-09-27 17:05 被阅读1154次
    MJRefresh

    MJRefresh小码哥开发,是目前iOS下拉刷新、上拉加载比较火的控件之一,有着超高的人气。
    本文主要介绍基于MJRefresh自定义下拉刷新动画。

    MJRefresh开源地址

    一、MJRefresh架构

    MJRefresh架构

    1、使用CocoaPods安装MJRefresh

    platform :ios, '7.0'
    pod 'MJRefresh', '~> 3.1.12'                # 下拉刷新
    

    二、自定义刷新动画(气球爆炸🎈)

    1、BallonRefresh架构

    BallonRefresh.bundle存放每一帧图片,命名为balloon_animation_x@2x.png,其中x标识每一帧,一共13帧图片。
    BallonRefreshHeader实现自定义刷新动画。

    2、BallonRefreshHeader.h文件中

    需要继承MJRefreshStateHeader

    #import "MJRefreshGifHeader.h"
    
    @interface BalloonRefreshHeader : MJRefreshStateHeader
    
    @end
    

    3、BallonRefreshHeader.m文件中

    实现思路:(每一帧动画时长0.15秒)
    (普通状态)使用1-5帧图片,用于放大缩小气球🎈
    (即将刷新、正在刷新状态)使用6-7帧图片,用于抖动气球🎈
    (刷新完成状态)使用8-13帧图片,用于爆炸气球🎈
    具体代码逻辑如下所示

    #import "BalloonRefreshHeader.h"
    
    #define BALLOON_GIF_DURATION 0.15
    
    @interface BalloonRefreshHeader()
    @property (strong, nonatomic) UIImageView *stateGIFImageView;
    @property (strong, nonatomic) NSMutableDictionary *stateImages;
    @end
    
    @implementation BalloonRefreshHeader
    
    #pragma mark - 懒加载
    - (UIImageView *)stateGIFImageView{
        if (!_stateGIFImageView) {
            _stateGIFImageView = [[UIImageView alloc] init];
            [self addSubview:_stateGIFImageView];
        }
        return _stateGIFImageView;
    }
    
    - (NSMutableDictionary *)stateImages {
        if (!_stateImages) {
            self.stateImages = [NSMutableDictionary dictionary];
        }
        return _stateImages;
    }
    
    #pragma mark - 公共方法
    - (void)setImages:(NSArray *)images forState:(MJRefreshState)state {
    
        if (images == nil) {
            return;
        }
        self.stateImages[@(state)] = images;
        /* 根据图片设置控件的高度 */
        UIImage *image = [images firstObject];
        if (image.size.height > self.mj_h) {
            self.mj_h = image.size.height;
        }
        
    }
    
    #pragma mark - 实现父类的方法
    - (void)prepare {
        
        [super prepare];
        // 初始化间距
        self.labelLeftInset = 20;
        // 资源数据(GIF每一帧)
        NSArray *idleImages = [self getRefreshingImageArrayWithStartIndex:1 endIndex:5];
        NSArray *refreshingImages = [self getRefreshingImageArrayWithStartIndex:6 endIndex:7];
        // 普通状态
        [self setImages:idleImages forState:MJRefreshStateIdle];
        // 即将刷新状态
        [self setImages:refreshingImages forState:MJRefreshStatePulling];
        // 正在刷新状态
        [self setImages:refreshingImages forState:MJRefreshStateRefreshing];
        
    }
    
    - (void)setPullingPercent:(CGFloat)pullingPercent {
        
        [super setPullingPercent:pullingPercent];
        NSArray *images = self.stateImages[@(MJRefreshStateIdle)];
        if (self.state != MJRefreshStateIdle || images.count == 0) {
            return;
        }
        [self.stateGIFImageView stopAnimating];
        NSUInteger index =  images.count * pullingPercent;
        if (index >= images.count) {
            index = images.count - 1;
        }
        self.stateGIFImageView.image = images[index];
        
    }
    
    - (void)placeSubviews{
        
        [super placeSubviews];
        if (self.stateGIFImageView.constraints.count) {
            return;
        }
        self.stateLabel.hidden = YES;
        self.lastUpdatedTimeLabel.hidden = YES;
        self.stateGIFImageView.frame = self.bounds;
        self.stateGIFImageView.contentMode = UIViewContentModeCenter;
        
    }
    
    - (void)setState:(MJRefreshState)state{
        
        MJRefreshCheckState
        if (state == MJRefreshStatePulling || state == MJRefreshStateRefreshing) {
            NSArray *images = self.stateImages[@(state)];
            [self startGIFViewAnimationWithImages:images];
        } else if (state == MJRefreshStateIdle) {
            if (oldState == MJRefreshStateRefreshing && state == MJRefreshStateIdle) {
                NSArray *endImages = [self getRefreshingImageArrayWithStartIndex:8 endIndex:13];
                
                [self startGIFViewAnimationWithImages:endImages];
            }else{
                [self.stateGIFImageView stopAnimating];
            }
        }
        
    }
    
    #pragma mark - 开始动画
    - (void)startGIFViewAnimationWithImages:(NSArray *)images{
        
        if (images.count <= 0){
            return;
        }
        [self.stateGIFImageView stopAnimating];
        // 单张
        if (images.count == 1) {
            self.stateGIFImageView.image = [images lastObject];
            return;
        }
        // 多张
        self.stateGIFImageView.animationImages = images;
        self.stateGIFImageView.animationDuration = images.count * BALLOON_GIF_DURATION;
        [self.stateGIFImageView startAnimating];
        
    }
    
    
    #pragma mark - 获取资源图片
    - (NSArray *)getRefreshingImageArrayWithStartIndex:(NSInteger)startIndex endIndex:(NSInteger)endIndex{
        
        NSMutableArray *result = [NSMutableArray array];
        for (NSUInteger i = startIndex; i <= endIndex; i++) {
            UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"BalloonRefresh.bundle/balloon_animation_%zd", i]];
            if (image) {
                [result addObject:image];
            }
        }
        return result;
        
    }
    @end
    

    三、如何使用BallonRefreshHeader

    1、将BallonRefreshHeader文件夹拖入工程中,代码如下。

    //模拟下拉刷新
    BalloonRefreshHeader *header = [BalloonRefreshHeader headerWithRefreshingBlock:^{
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            [mainTableView.mj_header endRefreshing];
        });
    }];
    mainTableView.mj_header = header;
    

    四、效果

    相关文章

      网友评论

      • HeavenWong:实现刷新动画,继承这个类MJRefreshGifHeader不是会更好吗
        Mr卿:@wendy_BabyWong 就是说 MJRefreshGifHeader 的内部 具体实现方式 有没有可能和楼主写的是一样的
        HeavenWong:@Mr卿 啥意思?:joy:
        Mr卿:大胆的猜测一下 ! MJRefreshGifHeader中的实现,是否可能和楼主一样!没去看过

      本文标题:玩转MJRefresh下拉刷新自定义动画

      本文链接:https://www.haomeiwen.com/subject/siwuextx.html