</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