相較于彈出加載框式的加載方式佩迟,下拉刷新式加載方式所帶來的用戶體驗(yàn)要好很多蚁鳖,當(dāng)前主流APP的下拉刷新動畫也是越來越絢麗,最近因?yàn)轫?xiàng)目需要婴噩,模仿美團(tuán)外賣的下拉刷新,對項(xiàng)目中的下拉刷新進(jìn)行了修改羽德。(其實(shí)是萬惡的設(shè)計(jì)師几莽,非要模仿人家的設(shè)計(jì),做為程序員只好費(fèi)盡腦細(xì)胞了宅静。)
dome我已經(jīng)上傳到GitHub上了章蚣,有需要的可朋友可以下載看看。
因?yàn)樵陧?xiàng)目中使用MJRefresh做為下拉刷新框架姨夹,因此所有的設(shè)計(jì)都是基于MJRefresh進(jìn)行的修改纤垂。而MJRefresh也算是當(dāng)前iOS開發(fā)使用的比較多的下拉刷新框架。
一磷账、普通動態(tài)效果
首先加載動態(tài)圖片在MJRefresh提供是提供的有現(xiàn)成的方法的峭沦,在MJRefreshGifHeader中,提供的就是加載動態(tài)圖片的方法逃糟,使用起來也比較簡單吼鱼。
我一般的做法是繼承MJRefreshGifHeader,重新創(chuàng)建一個(gè)類绰咽,用來設(shè)置動態(tài)圖片加載的一些基本屬性蛉抓。
1、 重寫下拉刷新的父類的方法
- (void)prepare{
[super prepare];
}
2剃诅、 更換動畫圖片
// 設(shè)置即將刷新狀態(tài)的動畫圖片(一松開就會刷新的狀態(tài))
NSMutableArray *refreshingImages = [NSMutableArray array];
for (int i = 1; i<=22; i++) {
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"gif_header_%d", i]];
[refreshingImages addObject:image];
}
// 設(shè)置正在刷新狀態(tài)的動畫圖片
[self setImages:refreshingImages forState:MJRefreshStateRefreshing];
3巷送、設(shè)計(jì)一些基本屬性
// 隱藏時(shí)間
self.lastUpdatedTimeLabel.hidden = YES;
// 隱藏狀態(tài)
self.stateLabel.hidden = YES;
// 下拉試圖高度
self.mj_h = 70;
二、模仿美團(tuán)外賣效果
如果只是實(shí)現(xiàn)加載動畫矛辕,那么上面的做法其實(shí)已經(jīng)能夠?qū)崿F(xiàn)了笑跛,可是如何才能實(shí)現(xiàn)上面那種隨著下拉距離付魔,圖片不斷放大的效果呢!
仔細(xì)分析MJRefreshGifHeader里面的效果不難發(fā)現(xiàn)飞蹂,如果是繼承于MJRefreshGifHeader是無法做到這樣的效果的几苍,那么很自然的就能想到,從MJRefreshGifHeader的父級來看看能否實(shí)現(xiàn)陈哑。
MJRefreshGifHeader的父級是MJRefreshStateHeader妻坝。
MJRefreshStateHeader里面的方法其實(shí)同MJRefreshGifHeader比較相似,比較重要的幾個(gè)方法分別是:
// 初始化方法
- (void)prepare{
[super prepare];
}
// 布局子視圖
- (void)placeSubviews {
}
// 拉拽的百分比
- (void)setPullingPercent:(CGFloat)pullingPercent {
[super setPullingPercent:pullingPercent];
}
// 下拉狀態(tài)
- (void)setState:(MJRefreshState)state {
MJRefreshCheckState
}
搞清楚了這幾個(gè)方法惊窖,接下來就比較簡單了
1刽宪、在初始方法中,設(shè)置下拉刷新的基礎(chǔ)屬性
// 初始化方法
- (void)prepare{
[super prepare];
// 隱藏時(shí)間
self.lastUpdatedTimeLabel.hidden = YES;
// 隱藏狀態(tài)
self.stateLabel.hidden = YES;
// 下拉試圖高度
self.mj_h = 70;
}
2界酒、在布局方法中創(chuàng)建imageView圣拄,用來展示動態(tài)圖片
// 布局子視圖
- (void)placeSubviews {
[super placeSubviews];
if (self.refreshImg.constraints.count) return;
// 刷新狀態(tài)狀態(tài)圖片
self.refreshImg.frame = self.bounds;
self.refreshImg.contentMode = UIViewContentModeCenter;
// 普通狀態(tài)狀態(tài)圖片
self.idleImg.x = 0;
self.idleImg.width = self.width;
self.idleImg.contentMode = UIViewContentModeCenter;
}
這里我分別創(chuàng)建了兩個(gè)imageView,分別用在下拉階段的放大縮小和加載階段的動畫展示毁欣,這主要是因?yàn)樵陂_發(fā)過程中庇谆,我發(fā)現(xiàn)如果使用一個(gè)imageView,就會造成在加載階段的動畫圖片尺寸變大的現(xiàn)象凭疮,具體是因?yàn)槭裁次乙矝]有找到原因饭耳。
3、在拖拽方法中执解,對普通狀態(tài)的圖片信息縮放
// 拉拽的百分比
- (void)setPullingPercent:(CGFloat)pullingPercent {
[super setPullingPercent:pullingPercent];
// 視圖正在下拉
if (0 < pullingPercent && pullingPercent <= 1) {
// 普通狀態(tài)圖片高度
self.idleImg.height = self.height - 70.0 * (1 - pullingPercent);
// 普通狀態(tài)圖片y值
self.idleImg.y = 70.0 * (1-pullingPercent);
// 普通狀態(tài)圖片
self.idleIm = [UIImage imageNamed:@"header"];
self.idleIm = [self scaleToSize:self.idleIm size:CGSizeMake(self.idleIm.size.width * pullingPercent, self.idleIm.size.height * pullingPercent)];
self.idleImg.image = self.idleIm;
}
}
在初始化方法中曾經(jīng)設(shè)置過一個(gè)屬性
// 下拉試圖高度
self.mj_h = 70;
這個(gè)屬性的意思就是當(dāng)下拉高度在070之間寞肖,拉拽的百分比屬性pullingPercent,就在01之間材鹦。也就是說我們在pullingPercent為0~1的時(shí)候逝淹,對圖片進(jìn)行縮放耕姊。為了保證無論下拉高度在什么位置桶唐,圖片都處在下拉區(qū)域的正中心,所有需要不停的改變圖片的位置
// 普通狀態(tài)圖片高度
self.idleImg.height = self.height - 70.0 * (1 - pullingPercent);
// 普通狀態(tài)圖片y值
self.idleImg.y = 70.0 * (1-pullingPercent);
圖片尺寸的修改方法茉兰,我進(jìn)行了一個(gè)封裝尤泽,
// 圖片縮放到指定大小尺寸
- (UIImage *)scaleToSize:(UIImage *)img size:(CGSize)size{
// 創(chuàng)建一個(gè)bitmap的context
// 并把它設(shè)置成為當(dāng)前正在使用的context
UIGraphicsBeginImageContext(size);
// 繪制改變大小的圖片
[img drawInRect:CGRectMake(0, 0, size.width, size.height)];
// 從當(dāng)前context中創(chuàng)建一個(gè)改變大小后的圖片
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
// 使當(dāng)前的context出堆棧
UIGraphicsEndImageContext();
// 返回新的改變大小后的圖片
return scaledImage;
}
4、最后一步规脸,就是在不同的刷新狀態(tài)進(jìn)行判斷坯约,然后對所需要展示的imageView進(jìn)行切換。
// 下拉狀態(tài)
- (void)setState:(MJRefreshState)state {
MJRefreshCheckState
switch (state) {
case MJRefreshStateIdle: { // 普通閑置狀態(tài)
// 停止刷新動畫
[self.refreshImg stopAnimating];
// 隱藏刷新狀態(tài)圖片
[self.refreshImg setHidden:YES];
// 展示普通狀態(tài)圖片
[self.idleImg setHidden:NO];
break;
}
case MJRefreshStateRefreshing: { // 正在刷新中的狀態(tài)
// 隱藏普通狀態(tài)圖片
[self.idleImg setHidden:YES];
// 展示刷新狀態(tài)圖片
[self.refreshImg setHidden:NO];
// 刷新狀態(tài)圖片
self.refreshImg.animationImages = @[[UIImage imageNamed:@"gif_header_1"], [UIImage imageNamed:@"gif_header_2"], [UIImage imageNamed:@"gif_header_3"], [UIImage imageNamed:@"gif_header_4"]];
self.refreshImg.animationDuration = 0.4;
// 開始刷新動畫
[self.refreshImg startAnimating];
break;
}
default:
break;
}
}
這里我只判斷了兩個(gè)狀態(tài)莫鸭,在MJRefresh中總共為我們5個(gè)不同的狀態(tài)
/** 普通閑置狀態(tài) */
MJRefreshStateIdle = 1,
/** 松開就可以進(jìn)行刷新的狀態(tài) */
MJRefreshStatePulling,
/** 正在刷新中的狀態(tài) */
MJRefreshStateRefreshing,
/** 即將刷新的狀態(tài) */
MJRefreshStateWillRefresh,
/** 所有數(shù)據(jù)加載完畢闹丐,沒有更多的數(shù)據(jù)了 */
MJRefreshStateNoMoreData
好了,到這里基本上就能實(shí)現(xiàn)上面圖片的功能了被因,不過有一個(gè)問題卿拴,我一直沒有解決衫仑,在進(jìn)行圖片大小縮放的時(shí)候,圖片會出現(xiàn)模糊的情況堕花,如果各位有人有解決方案的話文狱,在此先謝謝了。