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~

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM