zoukankan      html  css  js  c++  java
  • iOS MJRefresh下拉刷新(上拉加载)使用详解

    下拉刷新控件目前比较火的有好几种,本人用过MJRefresh 和 SVPullToRefresh,相对而言,前者比后者可定制化、拓展新都更高一点。

    因此本文着重讲一下MJRefresh的简单用法。

    导入项目:

    • cocoapods导入:pod 'MJRefresh'
    • 手动导入:
      • MJRefresh文件夹中的所有文件拽入项目中
      • 导入主头文件:#import "MJRefresh.h"

    下拉刷新:

    广泛性分为6种使用场景,分别对应:默认、动画图片、隐藏时间、隐藏时间和状态、自定义文字说明、以及自定义刷新控件。

    下面就各种场景分别讲一下:

    1、默认场景

     包含刷新菊花、下拉说明、时间

    使用代码:

    #pragma mark UITableView + 下拉刷新 默认
    - (void)example01
    {
        __weak __typeof(self) weakSelf = self;
        
        // 设置回调(一旦进入刷新状态就会调用这个refreshingBlock)
        self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
            [weakSelf loadNewData];
        }];
        
        // 马上进入刷新状态
        [self.tableView.mj_header beginRefreshing];
    }
    

      

    2、使用动画图片

    PS:这里的动画并不是用gif实现的,而是利用序列帧(即若干图片组成一个不同状态下的图片数组,然后根据位置显示不同图片)去展现。

    #pragma mark UITableView + 下拉刷新 动画图片
    - (void)example02
    {
        // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
        self.tableView.mj_header = [MJChiBaoZiHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
        
        // 马上进入刷新状态
        [self.tableView.mj_header beginRefreshing];
    }
    

    这里用大众点评吃包子图片为例,新建一个自定义类 MJChiBaoZiHeader,继承:MJRefreshGifHeader

    #import "MJRefreshGifHeader.h" 

    @interface MJChiBaoZiHeader : MJRefreshGifHeader 

    @end

    然后重写prepare方法,代码:

    - (void)prepare
    {
        [super prepare];
        
        // 设置普通状态的动画图片
        NSMutableArray *idleImages = [NSMutableArray array];
        for (NSUInteger i = 1; i<=60; i++) {
            UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_anim__000%zd", i]];
            [idleImages addObject:image];
        }
         [self setImages:idleImages forState:MJRefreshStateIdle];
        
        // 设置即将刷新状态的动画图片(一松开就会刷新的状态)
        NSMutableArray *refreshingImages = [NSMutableArray array];
        for (NSUInteger i = 1; i<=3; i++) {
            UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_loading_0%zd", i]];
            [refreshingImages addObject:image];
        }
        [self setImages:refreshingImages forState:MJRefreshStatePulling];
        
        // 设置正在刷新状态的动画图片
        [self setImages:refreshingImages forState:MJRefreshStateRefreshing];
    }
    

    关键点就是这里的两个图片数组,60是因为下拉控件默认拉动距离就是60距离,这里比较严谨,利用60张不同图片去对应每个距离点,当然实际中,我们可以缩减,不需要精确到每个距离点对应一张图片,这里个人自己决定。

    这里需要先了解下,下拉的五种状态。如下:

    /** 刷新控件的状态 */
    typedef NS_ENUM(NSInteger, MJRefreshState) {
        /** 普通闲置状态 */
        MJRefreshStateIdle = 1,
        /** 松开就可以进行刷新的状态 */
        MJRefreshStatePulling,
        /** 正在刷新中的状态 */
        MJRefreshStateRefreshing,
        /** 即将刷新的状态 */
        MJRefreshStateWillRefresh,
        /** 所有数据加载完毕,没有更多的数据了 */
        MJRefreshStateNoMoreData
    };
    

      

    idleImages图片数组对应闲置下拉状态,表示下拉到临界值前的展示图片。
    refreshingImages图片数组对应正在刷新时的动画展示图片,一般这里需要3~5张图片去模拟动画。

    重写完prepare方法,就可以实现动画了。

    3、下拉刷新 隐藏时间

     

    这里与默认的区别就是不显示上次刷新时间,使用方法:

    #pragma mark UITableView + 下拉刷新 隐藏时间
    - (void)example03
    {
        // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
        MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
        
        // 设置自动切换透明度(在导航栏下面自动隐藏)
        header.automaticallyChangeAlpha = YES;
        
        // 隐藏时间
        header.lastUpdatedTimeLabel.hidden = YES;
        
        // 马上进入刷新状态
        [header beginRefreshing];
        
        // 设置header
        self.tableView.mj_header = header;
    }
    

    4、下拉刷新 隐藏状态和时间

    这个场景一般适用于只需要动画展示,简洁清爽,也是用的蛮多的。

    同样,处理很简单。

    #pragma mark UITableView + 下拉刷新 隐藏状态和时间
    - (void)example04
    {
        // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
        MJChiBaoZiHeader *header = [MJChiBaoZiHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
        
        // 隐藏时间
        header.lastUpdatedTimeLabel.hidden = YES;
    
        // 隐藏状态
        header.stateLabel.hidden = YES;
        
        // 马上进入刷新状态
        [header beginRefreshing];
        
        // 设置header
        self.tableView.mj_header = header;
    }
    

      

    5、下拉刷新 自定义文字

    想自己DIY个性文字描述,一样很简单。

    不管是文字text、文字大小、还是颜色都一句话搞定。

    #pragma mark UITableView + 下拉刷新 自定义文字
    - (void)example05
    {
        // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
        MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
        
        // 设置文字
        [header setTitle:@"快扯我,快点" forState:MJRefreshStateIdle];
        [header setTitle:@"数据要来啦" forState:MJRefreshStatePulling];
        [header setTitle:@"服务器正在狂奔 ..." forState:MJRefreshStateRefreshing];
        
        // 设置字体
        header.stateLabel.font = [UIFont systemFontOfSize:15];
        header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:14];
    
        // 设置颜色
        header.stateLabel.textColor = [UIColor redColor];
        header.lastUpdatedTimeLabel.textColor = [UIColor grayColor];
        
        // 马上进入刷新状态
        [header beginRefreshing];
        
        // 设置刷新控件
        self.tableView.mj_header = header;
    }
    

      

    6、下拉刷新 自定义刷新控件

    上面的都不够玩,怎么办,没关系,还有最后一种更定制化的方法:自己加控件样式。

    这里不限于任何控件,我们可以在头部的这片区域,尽情添加Subviews,但记住一点,高度千万不要吵过header高度(默认60)。

    除了控件,甚至可以自己绘制动画等等。

    实现原理:同样先自定义自己的类,继承 MJRefreshHeader

    重写 prepare 方法,再重写 placeSubviews 方法 设置位置。

    代码:

    a、定义控件属性

    @interface MJDIYHeader()
    @property (weak, nonatomic) UILabel *label;
    @property (weak, nonatomic) UISwitch *s;
    @property (weak, nonatomic) UIImageView *logo;
    @property (weak, nonatomic) UIActivityIndicatorView *loading;
    @end
    

    b、重写prepare方法

    #pragma mark 在这里做一些初始化配置(比如添加子控件)
    - (void)prepare
    {
        [super prepare];    
        // 设置控件的高度
        self.mj_h = 50;
        
        // 添加label
        UILabel *label = [[UILabel alloc] init];
        label.textColor = [UIColor colorWithRed:1.0 green:0.5 blue:0.0 alpha:1.0];
        label.font = [UIFont boldSystemFontOfSize:16];
        label.textAlignment = NSTextAlignmentCenter;
        [self addSubview:label];
        self.label = label;
        
        // 打酱油的开关
        UISwitch *s = [[UISwitch alloc] init];
        [self addSubview:s];
        self.s = s;
        
        // logo
        UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Logo"]];
        logo.contentMode = UIViewContentModeScaleAspectFit;
        [self addSubview:logo];
        self.logo = logo;
        
        // loading
        UIActivityIndicatorView *loading = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        [self addSubview:loading];
        self.loading = loading;
    }
    

    c、重写 placeSubviews 

    #pragma mark 在这里设置子控件的位置和尺寸
    - (void)placeSubviews
    {
        [super placeSubviews];
    
        self.label.frame = self.bounds;
        
        self.logo.bounds = CGRectMake(0, 0, self.bounds.size.width, 100);
        self.logo.center = CGPointMake(self.mj_w * 0.5, - self.logo.mj_h + 20);
        
        self.loading.center = CGPointMake(self.mj_w - 30, self.mj_h * 0.5);
    }
    

    d、根据下拉位移,自定义不同位移的控件展示,比如显示不同文字,颜色等

    #pragma mark 监听控件的刷新状态
    - (void)setState:(MJRefreshState)state
    {
        MJRefreshCheckState;
    
        switch (state) {
            case MJRefreshStateIdle:
                [self.loading stopAnimating];
                [self.s setOn:NO animated:YES];
                self.label.text = @"赶紧下拉吖(开关是打酱油滴)";
                break;
            case MJRefreshStatePulling:
                [self.loading stopAnimating];
                [self.s setOn:YES animated:YES];
                self.label.text = @"赶紧放开我吧(开关是打酱油滴)";
                break;
            case MJRefreshStateRefreshing:
                [self.s setOn:YES animated:YES];
                self.label.text = @"加载数据中(开关是打酱油滴)";
                [self.loading startAnimating];
                break;
            default:
                break;
        }
    }
    

    上拉刷新:

    上拉刷新加载和下拉很类似,这里我只讲几点小注意点:

    1、MJRefreshBackNormalFooter 和 MJRefreshAutoNormalFooter都能实现上拉加载,

    不过两者有点区别:前者的上拉区域在tableview的底部,后者是紧跟在数据下方。这个大家可以视情况选择。

    2、如果选择的MJRefreshAutoNormalFooter,可能会遇到一个:“点击或上拉加载更多”会一直存在的问题,如何去掉呢?

    解决办法:

    1、修改源码,在MJRefreshConst.m里更改这句话:

    NSString *const MJRefreshAutoFooterIdleText = @"";

    2、设置isAutomaticallyChangeAlpha属性为yes。

    参考代码:

            let mjfoot = MJRefreshBackNormalFooter { 
                if weakself?.lastId == -1 || weakself?.pageIndex == -1{
                    weakself?.tableView.mj_footer.endRefreshingWithNoMoreData()
                    return
                }
                
                weakself?.requestData()
    
            }
            mjfoot?.setTitle("没有更多数据了", for: .noMoreData)
            mjfoot?.isAutomaticallyChangeAlpha = true
            tableView.mj_footer = mjfoot

    3、设置没有数据时,不显示上拉加载说明

      func setMJFooterVisible() {
            if ELList.count <= 0 {
                tableView.mj_footer.isHidden = true
            }else{
                tableView.mj_footer.isHidden = false
            }
      }

    4、修改刷新的提示语,这点下拉刷新和上拉加载都适用 ,再说明一下:

    这种需要先初始化一个header或footer,再设置settitle方法就好了。

        [header setTitle:@"快扯我,快点" forState:MJRefreshStateIdle];
        [header setTitle:@"数据要来啦" forState:MJRefreshStatePulling];
        [header setTitle:@"服务器正在狂奔 ..." forState:MJRefreshStateRefreshing];

    下载源码:https://github.com/CoderMJLee/MJRefresh

     

    enjoy~

      

  • 相关阅读:
    教你50招提升ASP.NET性能(二十一):避免使用会话状态
    教你50招提升ASP.NET性能(二十):7条便利的ViewState技巧
    教你50招提升ASP.NET性能(二十):认识你的循环
    教你50招提升ASP.NET性能(十九):静态集合
    教你50招提升ASP.NET性能(十八):在处理网站性能问题前,首先验证问题是否出在客户端
    教你50招提升ASP.NET性能(十七):不要认为问题只会从业务层产生
    教你50招提升ASP.NET性能(十六):把问题仍给硬件而不是开发人员
    教你50招提升ASP.NET性能(十五):解决性能问题时不要低估UI的价值
    教你50招提升ASP.NET性能(十四):使用startMode属性来减少ASP.NET站点加载时间
    Chrome谷歌浏览器书签排序后,重启浏览器导致排序无效的问题(完美解决)
  • 原文地址:https://www.cnblogs.com/yajunLi/p/5735990.html
Copyright © 2011-2022 走看看