iOS實(shí)現(xiàn)MJRefresh下拉刷新(上拉加載)使用詳解
下拉刷新控件目前比較火的有好幾種,本人用過(guò)MJRefresh 和 SVPullToRefresh,相對(duì)而言,前者比后者可定制化、拓展新都更高一點(diǎn)。
因此本文著重講一下MJRefresh的簡(jiǎn)單用法。
導(dǎo)入項(xiàng)目:
cocoapods導(dǎo)入:pod 'MJRefresh'
手動(dòng)導(dǎo)入:
- 將MJRefresh文件夾中的所有文件拽入項(xiàng)目中
- 導(dǎo)入主頭文件:#import "MJRefresh.h"
使用介紹:

廣泛性分為6種使用場(chǎng)景,分別對(duì)應(yīng):默認(rèn)、動(dòng)畫(huà)圖片、隱藏時(shí)間、隱藏時(shí)間和狀態(tài)、自定義文字說(shuō)明、以及自定義刷新控件。
下面就各種場(chǎng)景分別講一下:
1、默認(rèn)場(chǎng)景

包含刷新菊花、下拉說(shuō)明、時(shí)間
使用代碼:
#pragma mark UITableView + 下拉刷新 默認(rèn)
- (void)example01
{
__weak __typeof(self) weakSelf = self;
// 設(shè)置回調(diào)(一旦進(jìn)入刷新?tīng)顟B(tài)就會(huì)調(diào)用這個(gè)refreshingBlock)
self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
[weakSelf loadNewData];
}];
// 馬上進(jìn)入刷新?tīng)顟B(tài)
[self.tableView.mj_header beginRefreshing];
}
2、使用動(dòng)畫(huà)圖片

PS:這里的動(dòng)畫(huà)并不是用gif實(shí)現(xiàn)的,而是利用序列幀(即若干圖片組成一個(gè)不同狀態(tài)下的圖片數(shù)組,然后根據(jù)位置顯示不同圖片)去展現(xiàn)。
#pragma mark UITableView + 下拉刷新 動(dòng)畫(huà)圖片
- (void)example02
{
// 設(shè)置回調(diào)(一旦進(jìn)入刷新?tīng)顟B(tài),就調(diào)用target的action,也就是調(diào)用self的loadNewData方法)
self.tableView.mj_header = [MJChiBaoZiHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
// 馬上進(jìn)入刷新?tīng)顟B(tài)
[self.tableView.mj_header beginRefreshing];
}
這里用大眾點(diǎn)評(píng)吃包子圖片為例,新建一個(gè)自定義類(lèi) MJChiBaoZiHeader,繼承:MJRefreshGifHeader
#import "MJRefreshGifHeader.h" @interface MJChiBaoZiHeader : MJRefreshGifHeader @end
然后重寫(xiě)prepare方法,代碼:
- (void)prepare
{
[super prepare];
// 設(shè)置普通狀態(tài)的動(dòng)畫(huà)圖片
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];
// 設(shè)置即將刷新?tīng)顟B(tài)的動(dòng)畫(huà)圖片(一松開(kāi)就會(huì)刷新的狀態(tài))
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];
// 設(shè)置正在刷新?tīng)顟B(tài)的動(dòng)畫(huà)圖片
[self setImages:refreshingImages forState:MJRefreshStateRefreshing];
}
關(guān)鍵點(diǎn)就是這里的兩個(gè)圖片數(shù)組,60是因?yàn)橄吕丶J(rèn)拉動(dòng)距離就是60距離,這里比較嚴(yán)謹(jǐn),利用60張不同圖片去對(duì)應(yīng)每個(gè)距離點(diǎn),當(dāng)然實(shí)際中,我們可以縮減,不需要精確到每個(gè)距離點(diǎn)對(duì)應(yīng)一張圖片,這里個(gè)人自己決定。
這里需要先了解下,下拉的五種狀態(tài)。如下:
/** 刷新控件的狀態(tài) */
typedef NS_ENUM(NSInteger, MJRefreshState) {
/** 普通閑置狀態(tài) */
MJRefreshStateIdle = 1,
/** 松開(kāi)就可以進(jìn)行刷新的狀態(tài) */
MJRefreshStatePulling,
/** 正在刷新中的狀態(tài) */
MJRefreshStateRefreshing,
/** 即將刷新的狀態(tài) */
MJRefreshStateWillRefresh,
/** 所有數(shù)據(jù)加載完畢,沒(méi)有更多的數(shù)據(jù)了 */
MJRefreshStateNoMoreData
};
idleImages圖片數(shù)組對(duì)應(yīng)閑置下拉狀態(tài),表示下拉到臨界值前的展示圖片。
refreshingImages圖片數(shù)組對(duì)應(yīng)正在刷新時(shí)的動(dòng)畫(huà)展示圖片,一般這里需要3~5張圖片去模擬動(dòng)畫(huà)。<br><br>重寫(xiě)完<span class="s1">prepare方法,就可以實(shí)現(xiàn)動(dòng)畫(huà)了。<br><br></span>
3、下拉刷新 隱藏時(shí)間

這里與默認(rèn)的區(qū)別就是不顯示上次刷新時(shí)間,使用方法:
#pragma mark UITableView + 下拉刷新 隱藏時(shí)間
- (void)example03
{
// 設(shè)置回調(diào)(一旦進(jìn)入刷新?tīng)顟B(tài),就調(diào)用target的action,也就是調(diào)用self的loadNewData方法)
MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
// 設(shè)置自動(dòng)切換透明度(在導(dǎo)航欄下面自動(dòng)隱藏)
header.automaticallyChangeAlpha = YES;
// 隱藏時(shí)間
header.lastUpdatedTimeLabel.hidden = YES;
// 馬上進(jìn)入刷新?tīng)顟B(tài)
[header beginRefreshing];
// 設(shè)置header
self.tableView.mj_header = header;
}
4、下拉刷新 隱藏狀態(tài)和時(shí)間
這個(gè)場(chǎng)景一般適用于只需要?jiǎng)赢?huà)展示,簡(jiǎn)潔清爽,也是用的蠻多的。
同樣,處理很簡(jiǎn)單。
#pragma mark UITableView + 下拉刷新 隱藏狀態(tài)和時(shí)間
- (void)example04
{
// 設(shè)置回調(diào)(一旦進(jìn)入刷新?tīng)顟B(tài),就調(diào)用target的action,也就是調(diào)用self的loadNewData方法)
MJChiBaoZiHeader *header = [MJChiBaoZiHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
// 隱藏時(shí)間
header.lastUpdatedTimeLabel.hidden = YES;
// 隱藏狀態(tài)
header.stateLabel.hidden = YES;
// 馬上進(jìn)入刷新?tīng)顟B(tài)
[header beginRefreshing];
// 設(shè)置header
self.tableView.mj_header = header;
}
5、下拉刷新 自定義文字
想自己DIY個(gè)性文字描述,一樣很簡(jiǎn)單。
不管是文字text、文字大小、還是顏色都一句話(huà)搞定。


#pragma mark UITableView + 下拉刷新 自定義文字
- (void)example05
{
// 設(shè)置回調(diào)(一旦進(jìn)入刷新?tīng)顟B(tài),就調(diào)用target的action,也就是調(diào)用self的loadNewData方法)
MJRefreshNormalHeader *header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
// 設(shè)置文字
[header setTitle:@"快扯我,快點(diǎn)" forState:MJRefreshStateIdle];
[header setTitle:@"數(shù)據(jù)要來(lái)啦" forState:MJRefreshStatePulling];
[header setTitle:@"服務(wù)器正在狂奔 ..." forState:MJRefreshStateRefreshing];
// 設(shè)置字體
header.stateLabel.font = [UIFont systemFontOfSize:15];
header.lastUpdatedTimeLabel.font = [UIFont systemFontOfSize:14];
// 設(shè)置顏色
header.stateLabel.textColor = [UIColor redColor];
header.lastUpdatedTimeLabel.textColor = [UIColor grayColor];
// 馬上進(jìn)入刷新?tīng)顟B(tài)
[header beginRefreshing];
// 設(shè)置刷新控件
self.tableView.mj_header = header;
}
6、下拉刷新 自定義刷新控件
上面的都不夠玩,怎么辦,沒(méi)關(guān)系,還有最后一種更定制化的方法:自己加控件樣式。



這里不限于任何控件,我們可以在頭部的這片區(qū)域,盡情添加Subviews,但記住一點(diǎn),高度千萬(wàn)不要吵過(guò)header高度(默認(rèn)60)。
除了控件,甚至可以自己繪制動(dòng)畫(huà)等等。
實(shí)現(xiàn)原理:同樣先自定義自己的類(lèi),繼承 MJRefreshHeader
重寫(xiě) prepare 方法,再重寫(xiě) placeSubviews 方法 設(shè)置位置。
代碼:
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、重寫(xiě)prepare方法
#pragma mark 在這里做一些初始化配置(比如添加子控件)
- (void)prepare
{
[super prepare];
// 設(shè)置控件的高度
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;
// 打醬油的開(kāi)關(guān)
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、重寫(xiě) placeSubviews
#pragma mark 在這里設(shè)置子控件的位置和尺寸
- (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、根據(jù)下拉位移,自定義不同位移的控件展示,比如顯示不同文字,顏色等
#pragma mark 監(jiān)聽(tīng)控件的刷新?tīng)顟B(tài)
- (void)setState:(MJRefreshState)state
{
MJRefreshCheckState;
switch (state) {
case MJRefreshStateIdle:
[self.loading stopAnimating];
[self.s setOn:NO animated:YES];
self.label.text = @"趕緊下拉吖(開(kāi)關(guān)是打醬油滴)";
break;
case MJRefreshStatePulling:
[self.loading stopAnimating];
[self.s setOn:YES animated:YES];
self.label.text = @"趕緊放開(kāi)我吧(開(kāi)關(guān)是打醬油滴)";
break;
case MJRefreshStateRefreshing:
[self.s setOn:YES animated:YES];
self.label.text = @"加載數(shù)據(jù)中(開(kāi)關(guān)是打醬油滴)";
[self.loading startAnimating];
break;
default:
break;
}
}
上拉刷新加載其實(shí)和下拉是同理,只不過(guò)區(qū)別就是:
self.tableView.mj_header 變成 self.tableView.mj_footer,后面的類(lèi)也由
MJRefreshNormalHeader 變成 MJRefreshAutoNormalFooter。
實(shí)現(xiàn)原理是相同的。
下載源碼:http://xiazai.jb51.net/201701/yuanma/MJRefresh_jb51.rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
IOS 應(yīng)用之間的跳轉(zhuǎn)和數(shù)據(jù)傳遞詳解
這篇文章主要介紹了IOS 應(yīng)用之間的跳轉(zhuǎn)和數(shù)據(jù)傳遞詳解的相關(guān)資料,需要的朋友可以參考下2016-09-09
Flutter列表滾動(dòng)定位超強(qiáng)輔助庫(kù)使用示例詳解
這篇文章主要為大家介紹了Flutter列表滾動(dòng)定位超強(qiáng)輔助庫(kù)使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
iOS開(kāi)發(fā)網(wǎng)絡(luò)編程之?dāng)帱c(diǎn)續(xù)傳
在下載較大的文件的時(shí)候,一次不能下載完畢,這就需要用到斷點(diǎn)續(xù)傳,那么在IOS開(kāi)發(fā)中該如何實(shí)現(xiàn)呢,下面跟著小編一起通過(guò)本文來(lái)學(xué)習(xí)下。2016-08-08
iOS如何為導(dǎo)航欄添加播放動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了iOS如何為導(dǎo)航欄添加播放動(dòng)畫(huà)的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10
iOS實(shí)現(xiàn)視頻壓縮上傳實(shí)例代碼
本篇文章主要介紹了iOS實(shí)現(xiàn)視頻壓縮上傳實(shí)例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04

