iOS-MJRefresh框架底层实现原理
来源:互联网 发布:mac删除文件命令行 编辑:程序博客网 时间:2024/06/05 20:08
直接上代码:
**#import "ViewController.h"#import "MJExtension.h"#import "AFNetworking.h"#import "UIView+Frame.h"#import "TopicItem.h"@interface ViewController ()//* 请求管理者 @property (nonatomic, weak) AFHTTPSessionManager *mgr;/** 全部的帖子数据 */@property (nonatomic, strong) NSMutableArray *topics;/** 用来加载下一页数据 */@property (nonatomic, copy) NSString *maxtime;/******** 下拉刷新-header ********//** 下拉刷新控件 */@property (nonatomic, weak) UIView *header;/** 下拉刷新控件里面的文字 */@property (nonatomic, weak) UILabel *headerLabel;/** 是否为"松开立即刷新" */@property(nonatomic, assign, getter=isWillLoadingNewData) BOOL willLoadingNewData;/** 是否为"正在刷新" */@property(nonatomic, assign, getter=isLoadingNewData) BOOL loadingNewData;/******** 下拉刷新-header ********//******** 上拉刷新-footer ********//** 上拉刷新控件 */@property (nonatomic, weak) UIView *footer;/** 上拉刷新控件里面的文字 */@property (nonatomic, weak) UILabel *footerLabel;/** 是否正在加载更多数据 */@property(nonatomic, assign, getter=isLoadingMoreData) BOOL loadingMoreData;/******** 上拉刷新-footer ********/@end@implementation ViewController#pragma mark - 懒加载- (AFHTTPSessionManager *)mgr{ if (!_mgr) { _mgr = [AFHTTPSessionManager manager]; } return _mgr;}#pragma mark - 初始化- (void)viewDidLoad { [super viewDidLoad]; self.tableView.contentInset = UIEdgeInsetsMake(61, 0, 0, 0); // 集成刷新控件 [self setUpRefresh]; [self loadNewTopics];}/** * 集成刷新控件 */- (void)setUpRefresh{ // 下拉刷新:加载最新的数据 UIView *header = [[UIView alloc] init]; header.backgroundColor = [UIColor yellowColor]; header.height = 60; header.width = self.tableView.width; header.y = - header.height; [self.tableView addSubview:header]; self.header = header; UILabel *headerLabel = [[UILabel alloc] init]; headerLabel.text = @"下拉可以刷新"; headerLabel.width = self.tableView.width; headerLabel.height = header.height; headerLabel.textAlignment = NSTextAlignmentCenter; [header addSubview:headerLabel]; self.headerLabel = headerLabel; // 上拉刷新:加载更多的数据 UIView *footer = [[UIView alloc] init]; footer.backgroundColor = [UIColor orangeColor]; footer.height = 35; footer.hidden = YES; self.tableView.tableFooterView = footer; self.footer = footer; UILabel *footerLabel = [[UILabel alloc] init]; footerLabel.text = @"上拉可以加载更多"; footerLabel.width = self.tableView.width; footerLabel.height = footer.height; footerLabel.textAlignment = NSTextAlignmentCenter; [footer addSubview:footerLabel]; self.footerLabel = footerLabel;}#pragma mark - 数据处理/** * 加载最新的帖子数据 */- (void)loadNewTopics{ // 拼接请求参数 NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; parameters[@"a"] = @"list"; parameters[@"c"] = @"data"; parameters[@"type"] = @"1"; // 发送请求 [self.mgr GET:@"http://api.budejie.com/api/api_open.php" parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { // 存储maxtime self.maxtime = responseObject[@"info"][@"maxtime"]; // 字典数组 -> 模型数组 self.topics = [TopicItem mj_objectArrayWithKeyValuesArray:responseObject[@"list"]]; // 刷新表格 [self.tableView reloadData]; // 结束刷新 self.loadingNewData = NO; // 恢复顶部的内边距 [UIView animateWithDuration:0.25 animations:^{ UIEdgeInsets inset = self.tableView.contentInset; inset.top -= self.header.height; self.tableView.contentInset = inset; }]; // 有数据了 self.footer.hidden = NO; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"请求失败 - %@", error); // 结束刷新 self.loadingNewData = NO; // 恢复顶部的内边距 [UIView animateWithDuration:0.25 animations:^{ UIEdgeInsets inset = self.tableView.contentInset; inset.top -= self.header.height; self.tableView.contentInset = inset; }]; }];}/** * 加载更多的帖子数据 */- (void)loadMoreTopics{ // 拼接请求参数 NSMutableDictionary *parameters = [NSMutableDictionary dictionary]; parameters[@"a"] = @"list"; parameters[@"c"] = @"data"; parameters[@"type"] = @"1"; parameters[@"maxtime"] = self.maxtime; // 发送请求 [self.mgr GET:@"http://api.budejie.com/api/api_open.php" parameters:parameters success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { // 存储maxtime self.maxtime = responseObject[@"info"][@"maxtime"]; // 字典数组 -> 模型数组 NSArray *moreTopics = [TopicItem mj_objectArrayWithKeyValuesArray:responseObject[@"list"]]; [self.topics addObjectsFromArray:moreTopics]; // 刷新表格 [self.tableView reloadData]; // 结束刷新 self.loadingMoreData = NO; self.footerLabel.text = @"上拉可以加载更多"; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"请求失败 - %@", error); // 结束刷新 self.loadingMoreData = NO; self.footerLabel.text = @"上拉可以加载更多"; }];}#pragma mark - 代理方法/** * 当scrollView在滚动,就会调用这个代理方法 */- (void)scrollViewDidScroll:(UIScrollView *)scrollView{ // 处理下拉刷新 [self dealLoadNewData]; // 处理上拉加载更多 [self dealLoadMoreData];}/** * 当用户手松开(停止拖拽),就会调用这个代理方法 */- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ if (self.willLoadingNewData == NO || self.loadingNewData) return; // 增加顶部的内边距 [UIView animateWithDuration:0.25 animations:^{ UIEdgeInsets inset = self.tableView.contentInset; inset.top += self.header.height; self.tableView.contentInset = inset; }]; // 修改文字 self.headerLabel.text = @"正在刷新数据..."; // 正在刷新 self.loadingNewData = YES; // 发送请求 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self loadNewTopics]; });}/** * 处理下拉刷新 */- (void)dealLoadNewData{ if (self.loadingNewData) return; CGFloat offsetY = - (64 + self.header.height); if (self.tableView.contentOffset.y <= offsetY) { self.headerLabel.text = @"松开立即刷新"; self.willLoadingNewData = YES; } else { self.headerLabel.text = @"下拉可以刷新"; self.willLoadingNewData = NO; }}/** * 处理上拉加载更多 */- (void)dealLoadMoreData{ // 如果没有数据 或者 正在上拉刷新, 直接返回 if (self.topics.count == 0 || self.loadingMoreData) return; CGFloat offsetY = self.tableView.contentSize.height + self.tableView.contentInset.bottom - self.tableView.height; if (self.tableView.contentOffset.y >= offsetY) { self.loadingMoreData = YES; // 更改文字 self.footerLabel.text = @"正在加载更多的数据..."; // 加载更多的帖子数据 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [self loadMoreTopics]; }); }}#pragma mark - 数据源- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return self.topics.count;}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *ID = @"cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; } TopicItem *item = self.topics[indexPath.row]; cell.textLabel.text = item.name; cell.detailTextLabel.text = item.text; return cell;}@end
效果:
实现原理
在tableView上加上一个View,注意不是headerView,而是一个Y值为负数的普通View,下拉时候监听偏移量,改变View的内容显示。
在tableView下面加上一个footerView,监听偏移量,当footerView完全显示的时候加载更多数据。
基本代码已贴,有不清楚的可以讨论交流。**
0 0
- iOS-MJRefresh框架底层实现原理
- iOS-MJRefresh框架底层实现原理
- iOS kvo 底层实现原理
- iOS KVO底层实现原理
- MJRefresh实现原理(详细版)
- PhoneGap 底层框架实现原理 详解
- iOS中OC:block底层实现原理
- iOS的KVO底层实现原理
- iOS中KVO的底层实现原理
- iOS OC语言: Block底层实现原理
- iOS OC语言: Block底层实现原理
- iOS Block底层实现原理详解
- iOS OC语言: Block底层实现原理
- iOS OC语言: Block底层实现原理
- MJRefresh框架
- MJRefresh框架
- iOS-MJRefresh
- iOS中__block 关键字的底层实现原理
- 基于父窗口底图的透明控件设计
- DFA
- 高通平台Le X520 Android源码路径
- 软件工程视频总结(三)
- 数据结构实验之图论二:基于邻接表的广度优先搜索遍历
- iOS-MJRefresh框架底层实现原理
- 每日一linux命令(51)-------date命令
- 区间修改的离线查询(询问在修改后)
- Xcode没有模拟器编译项
- mysql在执行limit时的优化
- 数据结构实验之图论二:基于邻接表的广度优先搜索遍历
- 工作周报2016.08.08-2016.08.14
- MySQL导入.sql文件及常用命令
- 将Eclipse代码导入到AndroidStudio的两种方式