MJTableViewController.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. // 代码地址: https://github.com/CoderMJLee/MJRefresh
  2. // 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000
  3. // MJTableViewController.m
  4. // MJRefreshExample
  5. //
  6. // Created by MJ Lee on 15/3/4.
  7. // Copyright (c) 2015年 itcast. All rights reserved.
  8. //
  9. #import "MJTableViewController.h"
  10. #import "MJRefresh.h"
  11. #import "UIView+MJExtension.h"
  12. #import "MJTestViewController.h"
  13. static const CGFloat MJDuration = 2.0;
  14. /**
  15. * 随机数据
  16. */
  17. #define MJRandomData [NSString stringWithFormat:@"随机数据---%d", arc4random_uniform(1000000)]
  18. @interface MJTableViewController()
  19. /** 用来显示的假数据 */
  20. @property (strong, nonatomic) NSMutableArray *data;
  21. @end
  22. @implementation MJTableViewController
  23. #pragma mark - 示例代码
  24. /**
  25. * UITableView + 下拉刷新 传统
  26. */
  27. - (void)example01
  28. {
  29. __weak typeof(self) weakSelf = self;
  30. // 添加传统的下拉刷新
  31. [self.tableView addLegendHeader];
  32. // 设置回调(一旦进入刷新状态就会调用这个refreshingBlock)
  33. self.tableView.legendHeader.refreshingBlock = ^{
  34. [weakSelf loadNewData];
  35. };
  36. // 马上进入刷新状态
  37. [self.tableView.legendHeader beginRefreshing];
  38. /**
  39. 也可以这样使用
  40. self.tableView.header.refreshingBlock = ^{
  41. };
  42. [self.tableView.header beginRefreshing];
  43. 此时self.tableView.header == self.tableView.legendHeader
  44. */
  45. }
  46. /**
  47. * UITableView + 下拉刷新 动画图片
  48. */
  49. - (void)example02
  50. {
  51. // 添加动画图片的下拉刷新
  52. [self.tableView addGifHeader];
  53. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
  54. [self.tableView.gifHeader setRefreshingTarget:self refreshingAction:@selector(loadNewData)];
  55. // 设置普通状态的动画图片
  56. NSMutableArray *idleImages = [NSMutableArray array];
  57. for (NSUInteger i = 1; i<=60; i++) {
  58. UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_anim__000%zd", i]];
  59. [idleImages addObject:image];
  60. }
  61. [self.tableView.gifHeader setImages:idleImages forState:MJRefreshHeaderStateIdle];
  62. // 设置即将刷新状态的动画图片(一松开就会刷新的状态)
  63. NSMutableArray *refreshingImages = [NSMutableArray array];
  64. for (NSUInteger i = 1; i<=3; i++) {
  65. UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_loading_0%zd", i]];
  66. [refreshingImages addObject:image];
  67. }
  68. [self.tableView.gifHeader setImages:refreshingImages forState:MJRefreshHeaderStatePulling];
  69. // 设置正在刷新状态的动画图片
  70. [self.tableView.gifHeader setImages:refreshingImages forState:MJRefreshHeaderStateRefreshing];
  71. // 在这个例子中,即将刷新 和 正在刷新 用的是一样的动画图片
  72. // 马上进入刷新状态
  73. [self.tableView.gifHeader beginRefreshing];
  74. // 此时self.tableView.header == self.tableView.gifHeader
  75. }
  76. /**
  77. * UITableView + 下拉刷新 隐藏时间
  78. */
  79. - (void)example03
  80. {
  81. // 添加传统的下拉刷新
  82. [self.tableView addLegendHeader];
  83. // 隐藏时间
  84. self.tableView.header.updatedTimeHidden = YES;
  85. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
  86. [self.tableView.header setRefreshingTarget:self refreshingAction:@selector(loadNewData)];
  87. // 马上进入刷新状态
  88. [self.tableView.header beginRefreshing];
  89. // 此时self.tableView.header == self.tableView.legendHeader
  90. }
  91. /**
  92. * UITableView + 下拉刷新 隐藏状态和时间01
  93. */
  94. - (void)example04
  95. {
  96. // 添加动画图片的下拉刷新
  97. [self.tableView addGifHeader];
  98. // 隐藏时间
  99. self.tableView.header.updatedTimeHidden = YES;
  100. // 隐藏状态
  101. self.tableView.header.stateHidden = YES;
  102. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
  103. [self.tableView.header setRefreshingTarget:self refreshingAction:@selector(loadNewData)];
  104. // 设置普通状态的动画图片
  105. NSMutableArray *idleImages = [NSMutableArray array];
  106. for (NSUInteger i = 0; i<=72; i++) {
  107. UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"PullToRefresh_%03zd", i]];
  108. [idleImages addObject:image];
  109. }
  110. [self.tableView.gifHeader setImages:idleImages forState:MJRefreshHeaderStateIdle];
  111. // 设置正在刷新状态的动画图片
  112. NSMutableArray *refreshingImages = [NSMutableArray array];
  113. for (NSUInteger i = 73; i<=140; i++) {
  114. UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"PullToRefresh_%03zd", i]];
  115. [refreshingImages addObject:image];
  116. }
  117. [self.tableView.gifHeader setImages:refreshingImages forState:MJRefreshHeaderStateRefreshing];
  118. // 在这个例子中,即将刷新时没有动画图片
  119. // 马上进入刷新状态
  120. [self.tableView.header beginRefreshing];
  121. // 此时self.tableView.header == self.tableView.gifHeader
  122. // 由于动画图片是黑色的,所以故意设置tableView底色为黑色
  123. self.tableView.backgroundColor = [UIColor blackColor];
  124. }
  125. /**
  126. * UITableView + 下拉刷新 隐藏状态和时间02
  127. */
  128. - (void)example05
  129. {
  130. // 添加动画图片的下拉刷新
  131. [self.tableView addGifHeader];
  132. // 隐藏时间
  133. self.tableView.header.updatedTimeHidden = YES;
  134. // 隐藏状态
  135. self.tableView.header.stateHidden = YES;
  136. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
  137. [self.tableView.header setRefreshingTarget:self refreshingAction:@selector(loadNewData)];
  138. // 设置普通状态的动画图片
  139. NSMutableArray *idleImages = [NSMutableArray array];
  140. for (NSUInteger i = 1; i<=60; i++) {
  141. UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_anim__000%zd", i]];
  142. [idleImages addObject:image];
  143. }
  144. [self.tableView.gifHeader setImages:idleImages forState:MJRefreshHeaderStateIdle];
  145. // 设置即将刷新状态的动画图片(一松开就会刷新的状态)
  146. NSMutableArray *refreshingImages = [NSMutableArray array];
  147. for (NSUInteger i = 1; i<=3; i++) {
  148. UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_loading_0%zd", i]];
  149. [refreshingImages addObject:image];
  150. }
  151. [self.tableView.gifHeader setImages:refreshingImages forState:MJRefreshHeaderStatePulling];
  152. // 设置正在刷新状态的动画图片
  153. [self.tableView.gifHeader setImages:refreshingImages forState:MJRefreshHeaderStateRefreshing];
  154. // 在这个例子中,即将刷新 和 正在刷新 用的是一样的动画图片
  155. // 马上进入刷新状态
  156. [self.tableView.header beginRefreshing];
  157. // 此时self.tableView.header == self.tableView.gifHeader
  158. }
  159. /**
  160. * UITableView + 下拉刷新 自定义文字
  161. */
  162. - (void)example06
  163. {
  164. // 添加传统的下拉刷新
  165. [self.tableView addLegendHeader];
  166. // 设置文字
  167. [self.tableView.header setTitle:@"下拉can刷新噻" forState:MJRefreshHeaderStateIdle];
  168. [self.tableView.header setTitle:@"一放手马上刷新咯" forState:MJRefreshHeaderStatePulling];
  169. [self.tableView.header setTitle:@"MJ哥正在帮你刷新..." forState:MJRefreshHeaderStateRefreshing];
  170. // 设置字体
  171. self.tableView.header.font = [UIFont systemFontOfSize:15];
  172. // 设置颜色
  173. self.tableView.header.textColor = [UIColor redColor];
  174. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
  175. [self.tableView.header setRefreshingTarget:self refreshingAction:@selector(loadNewData)];
  176. // 马上进入刷新状态
  177. [self.tableView.header beginRefreshing];
  178. // 此时self.tableView.header == self.tableView.legendHeader
  179. }
  180. /**
  181. * UITableView + 上拉刷新 传统
  182. */
  183. - (void)example11
  184. {
  185. __weak typeof(self) weakSelf = self;
  186. // 添加传统的上拉刷新
  187. [self.tableView addLegendFooter];
  188. // 设置回调(一旦进入刷新状态就会调用这个refreshingBlock)
  189. self.tableView.legendFooter.refreshingBlock = ^{
  190. [weakSelf loadMoreData];
  191. };
  192. /**
  193. 也可以这样使用
  194. self.tableView.footer.refreshingBlock = ^{
  195. };
  196. 此时self.tableView.footer == self.tableView.legendFooter
  197. */
  198. }
  199. /**
  200. * UITableView + 上拉刷新 动画图片
  201. */
  202. - (void)example12
  203. {
  204. // 添加动画图片的上拉刷新
  205. [self.tableView addGifFooter];
  206. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法)
  207. [self.tableView.footer setRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
  208. // 设置正在刷新状态的动画图片
  209. NSMutableArray *refreshingImages = [NSMutableArray array];
  210. for (NSUInteger i = 1; i<=3; i++) {
  211. UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_loading_0%zd", i]];
  212. [refreshingImages addObject:image];
  213. }
  214. self.tableView.gifFooter.refreshingImages = refreshingImages;
  215. // 此时self.tableView.footer == self.tableView.gifFooter
  216. }
  217. /**
  218. * UITableView + 上拉刷新 隐藏状态01
  219. */
  220. - (void)example13
  221. {
  222. // 添加动画图片的上拉刷新
  223. [self.tableView addGifFooter];
  224. // 当上拉刷新控件出现50%时(出现一半),就会自动刷新。这个值默认是1.0(也就是上拉刷新100%出现时,才会自动刷新)
  225. // self.tableView.footer.appearencePercentTriggerAutoRefresh = 0.5;
  226. // 隐藏状态
  227. self.tableView.footer.stateHidden = YES;
  228. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法)
  229. [self.tableView.footer setRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
  230. // 设置正在刷新状态的动画图片
  231. NSMutableArray *refreshingImages = [NSMutableArray array];
  232. for (NSUInteger i = 73; i<=140; i++) {
  233. UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"PullToRefresh_%03zd", i]];
  234. [refreshingImages addObject:image];
  235. }
  236. self.tableView.gifFooter.refreshingImages = refreshingImages;
  237. // 此时self.tableView.footer == self.tableView.gifFooter
  238. // 由于动画图片是黑色的,所以故意设置tableView底色为黑色
  239. self.tableView.backgroundColor = [UIColor blackColor];
  240. }
  241. /**
  242. * UITableView + 上拉刷新 隐藏状态02
  243. */
  244. - (void)example14
  245. {
  246. // 添加动画图片的上拉刷新
  247. [self.tableView addGifFooter];
  248. // 隐藏状态
  249. self.tableView.footer.stateHidden = YES;
  250. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法)
  251. [self.tableView.footer setRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
  252. // 设置正在刷新状态的动画图片
  253. NSMutableArray *refreshingImages = [NSMutableArray array];
  254. for (NSUInteger i = 1; i<=3; i++) {
  255. UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"dropdown_loading_0%zd", i]];
  256. [refreshingImages addObject:image];
  257. }
  258. self.tableView.gifFooter.refreshingImages = refreshingImages;
  259. // 此时self.tableView.footer == self.tableView.gifFooter
  260. }
  261. /**
  262. * UITableView + 上拉刷新 全部加载完毕
  263. */
  264. - (void)example15
  265. {
  266. // 添加传统的上拉刷新
  267. [self.tableView addLegendFooter];
  268. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadLastData方法)
  269. [self.tableView.footer setRefreshingTarget:self refreshingAction:@selector(loadLastData)];
  270. // 此时self.tableView.footer == self.tableView.legendFooter
  271. // 其他
  272. self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"恢复数据加载" style:UIBarButtonItemStyleDone target:self action:@selector(recover)];
  273. }
  274. - (void)recover
  275. {
  276. [self.tableView.footer setRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
  277. // [self.tableView.footer beginRefreshing];
  278. self.tableView.footer.state = MJRefreshFooterStateIdle;
  279. // 此时self.tableView.footer == self.tableView.legendFooter
  280. }
  281. /**
  282. * UITableView + 上拉刷新 禁止自动加载
  283. */
  284. - (void)example16
  285. {
  286. // 添加传统的上拉刷新
  287. [self.tableView addLegendFooter];
  288. // 禁止自动加载
  289. self.tableView.footer.automaticallyRefresh = NO;
  290. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法)
  291. [self.tableView.footer setRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
  292. // 此时self.tableView.footer == self.tableView.legendFooter
  293. }
  294. /**
  295. * UITableView + 上拉刷新 自定义文字
  296. */
  297. - (void)example17
  298. {
  299. // 添加传统的上拉刷新
  300. [self.tableView addLegendFooter];
  301. // 设置文字
  302. [self.tableView.footer setTitle:@"轻点或者轻拽可加载更多" forState:MJRefreshFooterStateIdle];
  303. [self.tableView.footer setTitle:@"MJ哥正在帮你加载..." forState:MJRefreshFooterStateRefreshing];
  304. [self.tableView.footer setTitle:@"没有再多的数据了" forState:MJRefreshFooterStateNoMoreData];
  305. // 设置字体
  306. self.tableView.footer.font = [UIFont systemFontOfSize:17];
  307. // 设置颜色
  308. self.tableView.footer.textColor = [UIColor blueColor];
  309. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadMoreData方法)
  310. [self.tableView.footer setRefreshingTarget:self refreshingAction:@selector(loadMoreData)];
  311. // 此时self.tableView.footer == self.tableView.legendFooter
  312. }
  313. /**
  314. * UITableView + 上拉刷新 加载后隐藏
  315. */
  316. - (void)example18
  317. {
  318. // 添加传统的上拉刷新
  319. [self.tableView addLegendFooter];
  320. // 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadOnceData方法)
  321. [self.tableView.footer setRefreshingTarget:self refreshingAction:@selector(loadOnceData)];
  322. // 此时self.tableView.footer == self.tableView.legendFooter
  323. }
  324. #pragma mark - 数据处理相关
  325. /**
  326. * 下拉刷新数据
  327. */
  328. - (void)loadNewData
  329. {
  330. // 1.添加假数据
  331. for (int i = 0; i<5; i++) {
  332. [self.data insertObject:MJRandomData atIndex:0];
  333. }
  334. // 2.模拟2秒后刷新表格UI(真实开发中,可以移除这段gcd代码)
  335. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  336. // 刷新表格
  337. [self.tableView reloadData];
  338. // 拿到当前的下拉刷新控件,结束刷新状态
  339. [self.tableView.header endRefreshing];
  340. });
  341. }
  342. /**
  343. * 上拉加载更多数据
  344. */
  345. - (void)loadMoreData
  346. {
  347. // 1.添加假数据
  348. for (int i = 0; i<5; i++) {
  349. [self.data addObject:MJRandomData];
  350. }
  351. // 2.模拟2秒后刷新表格UI(真实开发中,可以移除这段gcd代码)
  352. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  353. // 刷新表格
  354. [self.tableView reloadData];
  355. // 拿到当前的上拉刷新控件,结束刷新状态
  356. [self.tableView.footer endRefreshing];
  357. });
  358. }
  359. /**
  360. * 加载最后一份数据
  361. */
  362. - (void)loadLastData
  363. {
  364. // 1.添加假数据
  365. for (int i = 0; i<5; i++) {
  366. [self.data addObject:MJRandomData];
  367. }
  368. // 2.模拟2秒后刷新表格UI(真实开发中,可以移除这段gcd代码)
  369. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  370. // 刷新表格
  371. [self.tableView reloadData];
  372. // 拿到当前的上拉刷新控件,变为没有更多数据的状态
  373. [self.tableView.footer noticeNoMoreData];
  374. });
  375. }
  376. /**
  377. * 只加载一次数据
  378. */
  379. - (void)loadOnceData
  380. {
  381. // 1.添加假数据
  382. for (int i = 0; i<25; i++) {
  383. [self.data addObject:MJRandomData];
  384. }
  385. // 2.模拟2秒后刷新表格UI(真实开发中,可以移除这段gcd代码)
  386. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(MJDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  387. // 刷新表格
  388. [self.tableView reloadData];
  389. // 隐藏当前的上拉刷新控件
  390. self.tableView.footer.hidden = YES;
  391. });
  392. }
  393. - (NSMutableArray *)data
  394. {
  395. if (!_data) {
  396. self.data = [NSMutableArray array];
  397. }
  398. return _data;
  399. }
  400. #pragma mark - 其他
  401. - (void)viewDidLoad
  402. {
  403. [super viewDidLoad];
  404. self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  405. [self performSelector:NSSelectorFromString(self.method) withObject:nil];
  406. }
  407. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  408. {
  409. return self.data.count;
  410. }
  411. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  412. {
  413. static NSString *ID = @"cell";
  414. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
  415. if (cell == nil) {
  416. cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
  417. }
  418. cell.textLabel.text = self.data[indexPath.row];;
  419. return cell;
  420. }
  421. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  422. {
  423. MJTestViewController *test = [[MJTestViewController alloc] init];
  424. if (indexPath.row % 2) {
  425. [self.navigationController pushViewController:test animated:YES];
  426. } else {
  427. UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:test];
  428. [self presentViewController:nav animated:YES completion:nil];
  429. }
  430. }
  431. - (void)dealloc
  432. {
  433. MJLog(@"%@销毁了", [self class]);
  434. }
  435. @end