1. 程式人生 > >iOS筆記-(利用EGORefreshTableHeaderView自定義上拉載入和下拉重新整理)

iOS筆記-(利用EGORefreshTableHeaderView自定義上拉載入和下拉重新整理)

</pre><p class="p1"></p><pre name="code" class="objc">GIthub下載一個DEMO,在RootviewController中檢視.
UIScrollViewDelegate:是監聽滑動的距離
EGORefreshTableHeaderDelegate:是頭部控制元件的代理方法.

//1.下拉到一定距離,手指放開會觸發:
(void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView*)view{
}
//2.資料載入完畢後,停止載入,檢視彈回原來位置,
- (void)doneLoadingTableViewData{
}

// 親手示範,建立工程
//1.
建立一個基本的BaseTableview,帶有下拉重新整理功能.
BaseTableview繼承UITableView.
//2.
匯入EGOTablePullRefresh資料夾到工程中.
#import  “EGORefreshTableHeaderView.h"
//3. 私有變數
EGORefreshTableHeaderView *_refreshHeaderView;//頭部控制元件

//4.不是所有的TableView都要下拉重新整理功能,此時新增
@property (nonatomic,assign) BOOL refreshHeader;//是否需要下拉效果

//5.在這裡新增頭部控制元件
//5-1
/*方法一
 *用XIB建立
*/
- (void)awakeFromNib{
    [self initHeaderView];
}
/* 方法二
 * 用程式碼建立
*/
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style{
    self = [super initWithFrame:frame style:style];
    if (self) {
        [self initHeaderView];
    }
    return self;
}

//5-2
//開啟下拉效果
    self.refreshHeader = YES;
//重寫下拉布爾型值
- (void)setRefreshHeader:(BOOL)refreshHeader{
    _refreshHeader = refreshHeader;
    if (_refreshHeader) {
        //開啟下拉效果,新增頭部控制元件
        [self addSubview:_refreshHeaderView];
    }else{
        //關閉下拉效果,移除頭部控制元件
        if ([_refreshHeaderView superview]) {
            [_refreshHeaderView removeFromSuperview];
        }
    }
}

//6.新增EGO代理方法..
#pragma mark -
#pragma mark Data Source Loading / Reloading Methods

- (void)reloadTableViewDataSource{
    _reloading = YES;
    
}

- (void)doneLoadingTableViewData{
    _reloading = NO;
    [_refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self];
    
}


#pragma mark -
#pragma mark UIScrollViewDelegate Methods

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    [_refreshHeaderView egoRefreshScrollViewDidScroll:scrollView];
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    [_refreshHeaderView egoRefreshScrollViewDidEndDragging:scrollView];
}


#pragma mark -
#pragma mark EGORefreshTableHeaderDelegate Methods

- (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView*)view{
    [self reloadTableViewDataSource];
    [self performSelector:@selector(doneLoadingTableViewData) withObject:nil afterDelay:3.0];
    
}

- (BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView*)view{
    return _reloading;
}

- (NSDate*)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView*)view{
    return [NSDate date];
}

//下拉,當手指放開時候,呼叫egoRefreshTableHeaderDidTriggerRefresh方法,此時
BaseTableView和控制器要進行通訊,BaseTableView通知控制器此時請求網路資料.(把自己self,路徑indexPath傳出去)
通訊方式用:通知,Block,Delegate.
在這我用Delegate.delegate方法並不一定會實現
所有判斷一下.因為是可選的
 if([self.baseDelegate respondsToSelector:@selector(pullDownWithTableView:)]){
        [self.baseDelegate pullDownWithTableView:self];
    }
//注意:因為BaseTableView繼承UITableView, 而且
BaseTableView遵守了UITableViewDelegate,UITableViewDataSource,所以在控制器中 不用遵守UITableViewDelegate,UITableViewDataSource.
在控制器中,當下拉載入完資料後,控制器做的事情是彈回原來位置.


//7.增加上拉控制元件
上拉控制元件可以放在taleView的尾部檢視.


//BaseTableView有個資料來源,陣列data.先判斷data是否有資料,無資料將尾部檢視隱藏;然後再判斷有資料時候,是否最後一頁.是最後一頁,”已載入全部資料”.

//點選尾部檢視”檢視更多”,載入資料時,尾部檢視變位”正在載入”.當載入完畢,尾部檢視變為原樣”檢視更多”.

//當載入到最後一頁,尾部檢視顯示為:“已載入全部資料”

//在控制器中,呼叫BaseTableView的reloadData時,複寫reloadData方法,讓控制器尾部檢視上拉載入完畢後停止風火輪的轉動.

//除了點選”檢視更多”按鈕能實現上拉載入,還可以設定當手指停止拖拽的時候,判斷scrollview的偏移量是否滿足 上拉載入.
(1)float offset = scrollView.contentOffset.y;
(2)float contentHeight = scrollView.contentSize.height;
(3)//當滑動到尾部檢視”檢視更多”,差值就是scrollView的高度
    float sub = contentHeight - offset;
if(sub - scrollView.bounds.size.height > 30){

}
</pre><pre name="code" class="objc">以下是原始碼,繼承BaseTableView,可以做更多有趣的上下拉載入資料效果...
<pre name="code" class="objc">//
//  BaseTableView.h
//  DEMOForEGOTalbeViewPullRefresh
//
//  Created by kun on 15/8/1.
//  Copyright (c) 2015年 kun. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "EGORefreshTableHeaderView.h"
/**
 *  定製協議,BaseTableView通知控制器去請求資料
 */
@class BaseTableView;
@protocol BaseTableViewDelegate <NSObject>
@optional
- (void)pullDownWithTableView:(BaseTableView *)baseTableView;//下拉重新整理
- (void)pullUpWithTableView:(BaseTableView *)baseTableView;  //上拉載入
- (void)baseTableView:(BaseTableView *)baseTableView didselectRowAtIndexPath:(NSIndexPath *)indexPath;//選中某一行
@end

@interface BaseTableView : UITableView<EGORefreshTableHeaderDelegate,UITableViewDelegate,UITableViewDataSource>{
    /**
     *  手動新增以下私有變數
     *  上拉控制元件
     */
    EGORefreshTableHeaderView *_refreshHeaderView;//頭部控制元件
    BOOL _reloading;//是否正在載入
    
    /**
     *  下拉控制元件
     */
    UIButton *_btnPullUp;
    UIActivityIndicatorView *_acitivityView;
}
@property (nonatomic,assign) BOOL refreshHeader;//是否需要下拉效果
@property (nonatomic,strong) NSArray *data;//為tableView提供資料
@property (nonatomic,weak) id <BaseTableViewDelegate>baseDelegate;
/**
 *  上拉載入完全部資料的標記
 */
@property (nonatomic,assign) BOOL isPullUpAllFinish;
/**
 *  資料載入完畢後,停止載入,檢視彈回原來位置
 */
- (void)doneLoadingTableViewData;
/**
 *  停止上拉載入
 */
- (void)stopPullUpLoadMore;
@end
</pre><pre name="code" class="objc">
</pre><pre name="code" class="objc">//
//  BaseTableView.m
//  DEMOForEGOTalbeViewPullRefresh
//
//  Created by kun on 15/8/1.
//  Copyright (c) 2015年 kun. All rights reserved.
//

#import "BaseTableView.h"

@implementation BaseTableView
/*方法一
 *用XIB建立
*/
- (void)awakeFromNib{
    //初始化下拉檢視
    [self initHeaderView];
    //初始化尾部控制元件
    [self initFooterView];
}
/* 方法二
 * 用程式碼建立
*/
- (instancetype)initWithFrame:(CGRect)frame style:(UITableViewStyle)style{
    self = [super initWithFrame:frame style:style];
    if (self) {
        //初始化下拉檢視
        [self initHeaderView];
        //初始化尾部控制元件
        [self initFooterView];
    }
    return self;
}

#pragma mark - init
//初始化頭部控制元件
- (void)initHeaderView{
    //1.設定頭部控制元件
    _refreshHeaderView = [[EGORefreshTableHeaderView alloc] initWithFrame:CGRectMake(0.0f, 0.0f - self.bounds.size.height, self.frame.size.width, self.bounds.size.height)];
    _refreshHeaderView.delegate = self;
    _refreshHeaderView.backgroundColor = [UIColor clearColor];
    
    //2.開啟下拉效果
    self.refreshHeader = YES;
    
    //3.新增tableView代理物件為BaseTableView
    self.dataSource = self;
    self.delegate   = self;
}

//初始化尾部控制元件
- (void)initFooterView{
    /**
     *  先建立"檢視更多"按鈕,當點選"檢視更多"按鈕,上拉資料,同時出現風火輪
     */
    //1.
    _btnPullUp = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    _btnPullUp.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 44);
    _btnPullUp.backgroundColor = [UIColor clearColor];
    [_btnPullUp setTitle:@"檢視更多" forState:UIControlStateNormal];
    [_btnPullUp addTarget:self action:@selector(pullUpToLoadMore) forControlEvents:UIControlEventTouchUpInside];
    self.tableFooterView = _btnPullUp;
    
    //2.風火輪設定
    UIActivityIndicatorView *activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    activityView.frame = CGRectMake(100, 10, 20, 20);
    [activityView stopAnimating];//初始化時停止旋轉。
    [_btnPullUp addSubview:activityView];
    _acitivityView = activityView;
}

//重寫下拉布爾型值
- (void)setRefreshHeader:(BOOL)refreshHeader{
    _refreshHeader = refreshHeader;
    if (_refreshHeader) {
        //開啟下拉效果,新增頭部控制元件
        [self addSubview:_refreshHeaderView];
    }else{
        //關閉下拉效果,移除頭部控制元件
        if ([_refreshHeaderView superview]) {
            [_refreshHeaderView removeFromSuperview];
        }
    }
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

#pragma mark - Action
//上拉載入更多
- (void)pullUpToLoadMore{
    //1.判斷代理方法是否執行
    if ([self.baseDelegate respondsToSelector:@selector(pullUpWithTableView:)]) {
        //1-1
        [self.baseDelegate pullUpWithTableView:self];
        //1-2.尾部檢視相應變化
        [self startPullUpLoadMore];
    }
    
}

#pragma mark - UITableViewDelegate
//(子類可以覆蓋父類的代理方法)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.data.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    if ([self.baseDelegate respondsToSelector:@selector(baseTableView:didselectRowAtIndexPath:)]) {
        [self.baseDelegate baseTableView:self didselectRowAtIndexPath:indexPath];
    }
}

- (void)reloadData{
    [super reloadData];
    //停止上拉載入更多
    [self stopPullUpLoadMore];
}

#pragma mark -
#pragma mark Data Source Loading / Reloading Methods

- (void)reloadTableViewDataSource{
    _reloading = YES;
    
}
//2.資料載入完畢後,停止載入,檢視彈回原來位置,
- (void)doneLoadingTableViewData{
    _reloading = NO;
    [_refreshHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self];
}


#pragma mark -
#pragma mark UIScrollViewDelegate Methods

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    [_refreshHeaderView egoRefreshScrollViewDidScroll:scrollView];
}

//當手指停止拖拽的時候呼叫.
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
    [_refreshHeaderView egoRefreshScrollViewDidEndDragging:scrollView];
    
    //1.判斷是否到最後一頁
    if(!self.isPullUpAllFinish){
        return;
    }
    
    //2.
   float offset = scrollView.contentOffset.y;
   float contentHeight = scrollView.contentSize.height;
    //當滑動到尾部檢視"檢視更多",差值就是scrollView的高度
    float sub = contentHeight - offset;
    if(scrollView.bounds.size.height - sub> 30){
        //2-1.控制狀態發生變化
        [self startPullUpLoadMore];
        //2-2.通知控制器,上拉載入更多
        if ([self.baseDelegate respondsToSelector:@selector(pullUpWithTableView:)]) {
            [self.baseDelegate pullUpWithTableView:self];
        }
    }
    
}


#pragma mark -
#pragma mark EGORefreshTableHeaderDelegate Methods
//1.下拉到一定距離,手指放開會觸發:
- (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView*)view{
    //1.設定為正在載入狀態
    [self reloadTableViewDataSource];
    
    //2.停止載入,彈回原來位置
    //2-1 除錯用
//    [self performSelector:@selector(doneLoadingTableViewData) withObject:nil afterDelay:3.0];
    //2-2 與控制器進行通訊
    if([self.baseDelegate respondsToSelector:@selector(pullDownWithTableView:)]){
        [self.baseDelegate pullDownWithTableView:self];
    }
}

- (BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView*)view{
    return _reloading;
}

- (NSDate*)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView*)view{
    return [NSDate date];
}


#pragma mark - Private
/**
 *  開始上拉載入
 */
- (void)startPullUpLoadMore{

        //1.文字發生變化
        _btnPullUp.enabled = NO;
        [_btnPullUp setTitle:@"正在載入..." forState:UIControlStateNormal];
        //2.風火輪轉動
        [_acitivityView startAnimating];
    
}

/**
 *  停止上拉載入
 */
- (void)stopPullUpLoadMore{
    //判斷是否有資料
    if (self.data.count > 0) {
        //0.顯示
        _btnPullUp.hidden = NO;
        //1.文字恢復原樣
        _btnPullUp.enabled = YES;
        [_btnPullUp setTitle:@"檢視更多" forState:UIControlStateNormal];
        //2.風火輪停止轉動
        [_acitivityView stopAnimating];
        //3.判斷是否最後一頁
        if(!self.isPullUpAllFinish){
         [_btnPullUp setTitle:@"已載入全部資料" forState:UIControlStateNormal];
            _btnPullUp.enabled = NO;
        }
    }else{
        _btnPullUp.hidden = YES;
    }
}

@end