IOS UITableView下拉刷新和上拉加载功能的实现
在IOS开发中UITableView是非常常用的一个功能,而在使用UITableView的时候我们经常要用到下拉刷新和上拉加载的功能,今天花时间实现了简单的UITableView的下拉刷新和上拉加载功能,效果图如下:

代码如下:
TableRefreshHeaderView.h
#import <UIKit/UIKit.h> @interface TableRefreshHeaderView : UIView @property(nonatomic, strong)UIImageView *arrowView; @property(nonatomic, strong)UILabel *refreshText; @property(nonatomic, strong)UIActivityIndicatorView *loadingIndicatorView; -(instancetype)initWithFrame:(CGRect)frame; - (void)setRefreshMode:(int)mode; @end
TableRefreshHeaderView.m
#import "TableRefreshHeaderView.h" #define UISCREEN_WIDTH [UIScreen mainScreen ].bounds.size.width
#define UISCREEN_HEIGHT [UIScreen mainScreen ].bounds.size.height @implementation TableRefreshHeaderView /*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/ -(instancetype)initWithFrame:(CGRect)frame;
{
self = [super initWithFrame:frame];
if (self) {
[self addSubview:self.arrowView];
[self addSubview:self.refreshText];
[self addSubview:self.loadingIndicatorView];
self.loadingIndicatorView.hidden = YES;
}
return self; } //箭头图片UIImageView
-(UIImageView *)arrowView
{
if (!_arrowView) {
_arrowView = [[UIImageView alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - , , , )];
_arrowView.image = [UIImage imageNamed:@"arrow"];
}
return _arrowView;
} //下拉刷新文字
-(UILabel *)refreshText
{
if (!_refreshText) {
_refreshText = [[UILabel alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - , , , )];
_refreshText.font = [UIFont fontWithName:@"Arial" size:];
_refreshText.textColor = [UIColor blackColor];
_refreshText.text = @"下拉刷新";
}
return _refreshText;
} //刷新旋转视图
- (UIActivityIndicatorView *)loadingIndicatorView
{
if (!_loadingIndicatorView) {
_loadingIndicatorView = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - , , , )];
[_loadingIndicatorView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
_loadingIndicatorView.backgroundColor = [UIColor clearColor];
_loadingIndicatorView.center = CGPointMake(UISCREEN_WIDTH / 2.0 - , );
}
return _loadingIndicatorView;
} //设置三种刷新模式
- (void)setRefreshMode:(int)mode
{
switch (mode) {
case ://下拉过程中
{
self.arrowView.hidden = NO;
self.loadingIndicatorView.hidden = YES;
[self.loadingIndicatorView stopAnimating];
[UIView animateWithDuration:0.3 animations:^(void){
_arrowView.transform = CGAffineTransformMakeRotation(M_PI * );
}];
self.refreshText.text = @"下拉刷新";
}
break;
case ://提示松开刷新
{
self.arrowView.hidden = NO;
self.loadingIndicatorView.hidden = YES;
[self.loadingIndicatorView stopAnimating];
[UIView animateWithDuration:0.3 animations:^(void){
_arrowView.transform = CGAffineTransformMakeRotation(M_PI);
}];
self.refreshText.text = @"松开刷新";
}
break;
case ://松开后刷新
{
self.arrowView.hidden = YES;
self.loadingIndicatorView.hidden = NO;
[self.loadingIndicatorView startAnimating];
self.refreshText.text = @"正在刷新"; }
break; default:
break;
}
} @end
TableRefreshFooterView.h
#import <UIKit/UIKit.h> @interface TableRefreshFooterView : UIView @property(nonatomic, strong) UIActivityIndicatorView *loadingIndcatorView; @property(nonatomic, strong) UILabel *loadingText; - (void)setLoadingMode:(int)mode; @end
TableRefreshFooterView.m
#import "TableRefreshFooterView.h" #define UISCREEN_WIDTH [UIScreen mainScreen ].bounds.size.width
#define UISCREEN_HEIGHT [UIScreen mainScreen ].bounds.size.height @implementation TableRefreshFooterView - (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self addSubview:self.loadingIndcatorView];
[self addSubview:self.loadingText];
}
return self;
} - (UIActivityIndicatorView *)loadingIndcatorView
{
if (!_loadingIndcatorView) {
_loadingIndcatorView = [[UIActivityIndicatorView alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - , , , )];
[_loadingIndcatorView setActivityIndicatorViewStyle:UIActivityIndicatorViewStyleGray];
_loadingIndcatorView.backgroundColor = [UIColor clearColor];
_loadingIndcatorView.center = CGPointMake(UISCREEN_WIDTH / 2.0 - , );
}
return _loadingIndcatorView;
} - (UILabel *)loadingText
{
if (!_loadingText) {
_loadingText = [[UILabel alloc]initWithFrame:CGRectMake(UISCREEN_WIDTH / 2.0 - , , , )];
_loadingText.font = [UIFont fontWithName:@"Arial" size:];
_loadingText.textColor = [UIColor blackColor];
_loadingText.text = @"加载中";
}
return _loadingText;
} - (void)setLoadingMode:(int)mode
{
switch (mode) {
case :
_loadingText.text = @"加载中";
[self.loadingIndcatorView startAnimating];
self.loadingIndcatorView.hidden = NO;
break;
case :
_loadingText.text = @"加载完毕";
[self.loadingIndcatorView stopAnimating];
self.loadingIndcatorView.hidden = YES;
break;
default:
break;
}
} /*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/ @end
ViewController.h
#import <UIKit/UIKit.h>
#import "TableRefreshHeaderView.h"
#import "TableRefreshFooterView.h" @interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource>
{
int rowCount;//行数
BOOL isLoading;//是否正在加载
BOOL isRefreshing;//是否正在刷新
int drageMode;//1为下拉刷新,2为上拉加载
} @property(nonatomic, strong)UITableView *myTableView; @property(nonatomic, strong)TableRefreshHeaderView *refreshHeaderView; @property(nonatomic, strong)TableRefreshFooterView *loadingFooterView; @end
ViewController.m
#import "ViewController.h"
#define UISCREEN_WIDTH [UIScreen mainScreen ].bounds.size.width
#define UISCREEN_HEIGHT [UIScreen mainScreen ].bounds.size.height
@interface ViewController () @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
rowCount = ;
isLoading = NO;
isRefreshing = NO;
drageMode = -;
[self.view addSubview:self.myTableView];
[self.myTableView addSubview:self.refreshHeaderView];
[self.myTableView addSubview:self.loadingFooterView];
[self.myTableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil]; // Do any additional setup after loading the view, typically from a nib.
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (void)dealloc
{
[self.myTableView removeObserver:self forKeyPath:@"contentOffset"];
} - (UITableView *)myTableView
{
if (!_myTableView) {
_myTableView = [[UITableView alloc]initWithFrame:CGRectMake(, , UISCREEN_WIDTH, UISCREEN_HEIGHT - )];
_myTableView.delegate = self;
_myTableView.dataSource = self;
}
return _myTableView;
} - (TableRefreshHeaderView *)refreshHeaderView
{
if (!_refreshHeaderView) {
_refreshHeaderView = [[TableRefreshHeaderView alloc]initWithFrame:CGRectMake(, -, UISCREEN_WIDTH, )];
}
return _refreshHeaderView;
} - (TableRefreshFooterView *)loadingFooterView
{
if (!_loadingFooterView) {
_loadingFooterView = [[TableRefreshFooterView alloc]initWithFrame:CGRectMake(, self.myTableView.contentSize.height, UISCREEN_WIDTH, )];
}
return _loadingFooterView;
} - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return rowCount;
} - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return ;
} - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}
cell.textLabel.text=[NSString stringWithFormat:@"%ld",indexPath.row+];
return cell;
} -(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
//如果列表控件加载完毕且当前为下拉加载,则将下拉加载视图移到列表可视范围之外
if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row && drageMode == ){
self.myTableView.contentInset = UIEdgeInsetsMake(, , , );
}
} //监听UITableview的顶部和头部下拉事件
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"contentOffset"] && !isLoading && !isRefreshing) {
self.loadingFooterView.frame = CGRectMake(, self.myTableView.contentSize.height, UISCREEN_WIDTH, );
if (self.myTableView.isDragging) {
if (self.myTableView.contentOffset.y > -) {
[self.refreshHeaderView setRefreshMode:];
}
else if (self.myTableView.contentOffset.y < -)
{
[self.refreshHeaderView setRefreshMode:];
}
}
else
{
if (self.myTableView.contentOffset.y < -)
{
drageMode = ;
self.myTableView.contentInset = UIEdgeInsetsMake(, , , );
[self.refreshHeaderView setRefreshMode:];
[self beginRefresh];
}
else if (self.myTableView.contentOffset.y > self.myTableView.contentSize.height - self.myTableView.frame.size.height + )
{
drageMode = ;
if (rowCount < ) {
[self.loadingFooterView setLoadingMode:];
[self beginLoading];
}
else
{
[self.loadingFooterView setLoadingMode:];
self.myTableView.contentInset = UIEdgeInsetsMake(, , , );
}
}
}
}
} //开始刷新
- (void)beginRefresh
{
dispatch_async(dispatch_get_global_queue(, ), ^{
isRefreshing = YES;
sleep();//处理耗时操作
dispatch_async(dispatch_get_main_queue(), ^{
[self endRefresh];//处理完之后更新界面
});
}) ;
} //停止刷新
- (void)endRefresh
{
[UIView animateWithDuration:0.3 animations:^{
self.myTableView.contentInset = UIEdgeInsetsMake(, , , );
}];
[self.refreshHeaderView setRefreshMode:];
isRefreshing = NO;
} //开始加载
- (void)beginLoading
{
dispatch_async(dispatch_get_global_queue(, ), ^{
isLoading = YES;
rowCount += ;
self.myTableView.contentInset = UIEdgeInsetsMake(, , , );
sleep();//处理耗时操作
dispatch_async(dispatch_get_main_queue(), ^{
[self.myTableView reloadData];
[self endLoading];//处理完之后更新界面
});
}) ;
} //停止加载
- (void)endLoading
{
if (rowCount >= ) {
[self.loadingFooterView setLoadingMode:];
self.myTableView.contentInset = UIEdgeInsetsMake(, , , );
}
else
{
self.myTableView.contentInset = UIEdgeInsetsMake(, , , );
[self.loadingFooterView setLoadingMode:];
}
isLoading = NO;
} @end
源码下载地址:http://download.csdn.net/detail/lzm2625347497/9601843
IOS UITableView下拉刷新和上拉加载功能的实现的更多相关文章
- android--------自定义控件ListView实现下拉刷新和上拉加载
开发项目过程中基本都会用到listView的下拉刷新和上滑加载更多,为了方便重写的ListView来实现下拉刷新,同时添加了上拉自动加载更多的功能. Android下拉刷新可以分为两种情况: 1.获取 ...
- IOS 开发下拉刷新和上拉加载更多
IOS 开发下拉刷新和上拉加载更多 简介 1.常用的下拉刷新的实现方式 (1)UIRefreshControl (2)EGOTTableViewrefresh (3)AH3DPullRefresh ( ...
- 下拉刷新和上拉加载 Swift
转载自:http://iyiming.me/blog/2015/07/05/custom-refresh-and-loading/ 关于下拉刷新和上拉加载,项目中一直使用MJRefresh(原先还用过 ...
- iOS下拉刷新和上拉刷新
在iOS开发中,我们经常要用到下拉刷新和上拉刷新来加载新的数据,当前这也适合分页.iOS原生就带有该方法,下面就iOS自带的下拉刷新方法来简单操作. 上拉刷新 1.在TableView里,一打开软件, ...
- Android 5.X新特性之为RecyclerView添加下拉刷新和上拉加载及SwipeRefreshLayout实现原理
RecyclerView已经写过两篇文章了,分别是Android 5.X新特性之RecyclerView基本解析及无限复用 和 Android 5.X新特性之为RecyclerView添加Header ...
- iscroll.js 下拉刷新和上拉加载
html代码如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...
- Android 使用PullToRefresh实现下拉刷新和上拉加载(ExpandableListView)
PullToRefresh是一套实现非常好的下拉刷新库,它支持: 1.ListView 2.ExpandableListView 3.GridView 4.WebView 等多种常用的需要刷新的Vie ...
- 使用PullToRefresh实现下拉刷新和上拉加载
使用PullToRefresh实现下拉刷新和上拉加载 分类: Android2013-12-20 15:51 78158人阅读 评论(91) 收藏 举报 Android下拉刷新上拉加载PullToRe ...
- H5下拉刷新和上拉加载实现原理浅析
前言 在移动端H5网页中,下拉刷新和上拉加载更多数据的交互方式出现频率很高,开源社区也有很多类似的解决方案,如iscroll,pulltorefresh.js库等.下面是对这两种常见交互基本实现原理的 ...
随机推荐
- C语言位运算详解[转]
作者:911 说明:本文参考了http://www2.tsu.edu.cn/www/cjc/online/cyuyan/,算是对其的修正,在此将本文列为原创,实有抄袭之嫌疑.甚是惭愧! 位运算是指按二 ...
- MySQL数据库主键设计原则
目录 1. 主键定义... 5 2. 主键设计原则... 5 2.1 确保主键的无意义性... 5 2.2 采用整型主键... 5 2.3 减少主键的变动... 5 2.4 避免重复使用主键... 6 ...
- MongoDB与.NET结合使用一(mongodb在windows 2003上的安装)
mongodb发展至今已经到2.6版本了,自从获得了1亿美元的风投之后,发展速度更是比以前快了很多,前段时间因为要用缓存,也比较了mongodb,大家也都觉得比较适合做无关系化的大数据存储,所以系统统 ...
- ORM SQLOBJECT SIMPLE
step01: (Install sqlobject) sudo easy_install sqlobject step02: (Connect MySQL) step03: (Install sup ...
- Atitit WebDriver技术规范原理与概念
Atitit WebDriver技术规范原理与概念 1. Book haosyo ma1 2. WebDriver是W3C的一个标准,由Selenium主持.1 3. WebDriver如何工作 (z ...
- paip.spring 获取bean getBean 没有beanid的情况下
paip.spring 获取bean getBean 没有beanid的情况下 spring能自动扫描带有注解的bean文件.. 作者Attilax 艾龙, EMAIL:1466519819@q ...
- paip.java 多线程参数以及返回值Future FutureTask 的使用.
paip.java 多线程参数以及返回值Future FutureTask 的使用. 在并发编程时,一般使用runnable,然后扔给线程池完事,这种情况下不需要线程的结果. 所以run的返回值是vo ...
- 详解eNSP下的PPP之MP、PAP/CHAP认证实验配置
一.PPP MP实验(用虚拟模板配置) 1.拓扑图
- 智能配置item
iTerm配置说明 ==== **这是一个很智能的配置,不论你电脑里面有没有安装iTerm,不管你有没有.zshrc配置文件,git配置文件,git忽略文件,以及git的默认编辑器都已经更改为vim, ...
- iOS:如何通过UIEdgeInsetsMake来制作可伸缩的Button
注:本文翻译自国外iOS开发者Natasha The Robot的一篇博文,链接在此.在iOS应用中,经常会有很多Button有相同的背景图片,却由于处在不同的位置而大小不同(尽管在iOS7中Butt ...