在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下拉刷新和上拉加载功能的实现的更多相关文章

  1. android--------自定义控件ListView实现下拉刷新和上拉加载

    开发项目过程中基本都会用到listView的下拉刷新和上滑加载更多,为了方便重写的ListView来实现下拉刷新,同时添加了上拉自动加载更多的功能. Android下拉刷新可以分为两种情况: 1.获取 ...

  2. IOS 开发下拉刷新和上拉加载更多

    IOS 开发下拉刷新和上拉加载更多 简介 1.常用的下拉刷新的实现方式 (1)UIRefreshControl (2)EGOTTableViewrefresh (3)AH3DPullRefresh ( ...

  3. 下拉刷新和上拉加载 Swift

    转载自:http://iyiming.me/blog/2015/07/05/custom-refresh-and-loading/ 关于下拉刷新和上拉加载,项目中一直使用MJRefresh(原先还用过 ...

  4. iOS下拉刷新和上拉刷新

    在iOS开发中,我们经常要用到下拉刷新和上拉刷新来加载新的数据,当前这也适合分页.iOS原生就带有该方法,下面就iOS自带的下拉刷新方法来简单操作. 上拉刷新 1.在TableView里,一打开软件, ...

  5. Android 5.X新特性之为RecyclerView添加下拉刷新和上拉加载及SwipeRefreshLayout实现原理

    RecyclerView已经写过两篇文章了,分别是Android 5.X新特性之RecyclerView基本解析及无限复用 和 Android 5.X新特性之为RecyclerView添加Header ...

  6. iscroll.js 下拉刷新和上拉加载

    html代码如下 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...

  7. Android 使用PullToRefresh实现下拉刷新和上拉加载(ExpandableListView)

    PullToRefresh是一套实现非常好的下拉刷新库,它支持: 1.ListView 2.ExpandableListView 3.GridView 4.WebView 等多种常用的需要刷新的Vie ...

  8. 使用PullToRefresh实现下拉刷新和上拉加载

    使用PullToRefresh实现下拉刷新和上拉加载 分类: Android2013-12-20 15:51 78158人阅读 评论(91) 收藏 举报 Android下拉刷新上拉加载PullToRe ...

  9. H5下拉刷新和上拉加载实现原理浅析

    前言 在移动端H5网页中,下拉刷新和上拉加载更多数据的交互方式出现频率很高,开源社区也有很多类似的解决方案,如iscroll,pulltorefresh.js库等.下面是对这两种常见交互基本实现原理的 ...

随机推荐

  1. C语言位运算详解[转]

    作者:911 说明:本文参考了http://www2.tsu.edu.cn/www/cjc/online/cyuyan/,算是对其的修正,在此将本文列为原创,实有抄袭之嫌疑.甚是惭愧! 位运算是指按二 ...

  2. MySQL数据库主键设计原则

    目录 1. 主键定义... 5 2. 主键设计原则... 5 2.1 确保主键的无意义性... 5 2.2 采用整型主键... 5 2.3 减少主键的变动... 5 2.4 避免重复使用主键... 6 ...

  3. MongoDB与.NET结合使用一(mongodb在windows 2003上的安装)

    mongodb发展至今已经到2.6版本了,自从获得了1亿美元的风投之后,发展速度更是比以前快了很多,前段时间因为要用缓存,也比较了mongodb,大家也都觉得比较适合做无关系化的大数据存储,所以系统统 ...

  4. ORM SQLOBJECT SIMPLE

    step01: (Install sqlobject) sudo easy_install sqlobject step02: (Connect MySQL) step03: (Install sup ...

  5. Atitit WebDriver技术规范原理与概念

    Atitit WebDriver技术规范原理与概念 1. Book haosyo ma1 2. WebDriver是W3C的一个标准,由Selenium主持.1 3. WebDriver如何工作 (z ...

  6. paip.spring 获取bean getBean 没有beanid的情况下

    paip.spring 获取bean  getBean 没有beanid的情况下 spring能自动扫描带有注解的bean文件.. 作者Attilax  艾龙,  EMAIL:1466519819@q ...

  7. paip.java 多线程参数以及返回值Future FutureTask 的使用.

    paip.java 多线程参数以及返回值Future FutureTask 的使用. 在并发编程时,一般使用runnable,然后扔给线程池完事,这种情况下不需要线程的结果. 所以run的返回值是vo ...

  8. 详解eNSP下的PPP之MP、PAP/CHAP认证实验配置

    一.PPP MP实验(用虚拟模板配置) 1.拓扑图

  9. 智能配置item

    iTerm配置说明 ==== **这是一个很智能的配置,不论你电脑里面有没有安装iTerm,不管你有没有.zshrc配置文件,git配置文件,git忽略文件,以及git的默认编辑器都已经更改为vim, ...

  10. iOS:如何通过UIEdgeInsetsMake来制作可伸缩的Button

    注:本文翻译自国外iOS开发者Natasha The Robot的一篇博文,链接在此.在iOS应用中,经常会有很多Button有相同的背景图片,却由于处在不同的位置而大小不同(尽管在iOS7中Butt ...