MJRefreshHeader.m 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  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. // MJRefreshHeader.m
  4. // MJRefreshExample
  5. //
  6. // Created by MJ Lee on 15/3/4.
  7. // Copyright (c) 2015年 小码哥. All rights reserved.
  8. //
  9. #import "MJRefreshHeader.h"
  10. @interface MJRefreshHeader()
  11. @property (assign, nonatomic) CGFloat insetTDelta;
  12. @end
  13. @implementation MJRefreshHeader
  14. #pragma mark - 构造方法
  15. + (instancetype)headerWithRefreshingBlock:(MJRefreshComponentRefreshingBlock)refreshingBlock
  16. {
  17. MJRefreshHeader *cmp = [[self alloc] init];
  18. cmp.refreshingBlock = refreshingBlock;
  19. return cmp;
  20. }
  21. + (instancetype)headerWithRefreshingTarget:(id)target refreshingAction:(SEL)action
  22. {
  23. MJRefreshHeader *cmp = [[self alloc] init];
  24. [cmp setRefreshingTarget:target refreshingAction:action];
  25. return cmp;
  26. }
  27. #pragma mark - 覆盖父类的方法
  28. - (void)prepare
  29. {
  30. [super prepare];
  31. // 设置key
  32. self.lastUpdatedTimeKey = MJRefreshHeaderLastUpdatedTimeKey;
  33. // 设置高度
  34. self.mj_h = MJRefreshHeaderHeight;
  35. }
  36. - (void)placeSubviews
  37. {
  38. [super placeSubviews];
  39. // 设置y值(当自己的高度发生改变了,肯定要重新调整Y值,所以放到placeSubviews方法中设置y值)
  40. self.mj_y = - self.mj_h - self.ignoredScrollViewContentInsetTop;
  41. }
  42. - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
  43. {
  44. [super scrollViewContentOffsetDidChange:change];
  45. // 在刷新的refreshing状态
  46. if (self.state == MJRefreshStateRefreshing) {
  47. if (self.window == nil) return;
  48. // sectionheader停留解决
  49. CGFloat insetT = - self.scrollView.mj_offsetY > _scrollViewOriginalInset.top ? - self.scrollView.mj_offsetY : _scrollViewOriginalInset.top;
  50. insetT = insetT > self.mj_h + _scrollViewOriginalInset.top ? self.mj_h + _scrollViewOriginalInset.top : insetT;
  51. self.scrollView.mj_insetT = insetT;
  52. self.insetTDelta = _scrollViewOriginalInset.top - insetT;
  53. return;
  54. }
  55. // 跳转到下一个控制器时,contentInset可能会变
  56. _scrollViewOriginalInset = self.scrollView.mj_inset;
  57. // 当前的contentOffset
  58. CGFloat offsetY = self.scrollView.mj_offsetY;
  59. // 头部控件刚好出现的offsetY
  60. CGFloat happenOffsetY = - self.scrollViewOriginalInset.top;
  61. // 如果是向上滚动到看不见头部控件,直接返回
  62. // >= -> >
  63. if (offsetY > happenOffsetY) return;
  64. // 普通 和 即将刷新 的临界点
  65. CGFloat normal2pullingOffsetY = happenOffsetY - self.mj_h;
  66. CGFloat pullingPercent = (happenOffsetY - offsetY) / self.mj_h;
  67. if (self.scrollView.isDragging) { // 如果正在拖拽
  68. self.pullingPercent = pullingPercent;
  69. if (self.state == MJRefreshStateIdle && offsetY < normal2pullingOffsetY) {
  70. // 转为即将刷新状态
  71. self.state = MJRefreshStatePulling;
  72. } else if (self.state == MJRefreshStatePulling && offsetY >= normal2pullingOffsetY) {
  73. // 转为普通状态
  74. self.state = MJRefreshStateIdle;
  75. }
  76. } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开
  77. // 开始刷新
  78. [self beginRefreshing];
  79. } else if (pullingPercent < 1) {
  80. self.pullingPercent = pullingPercent;
  81. }
  82. }
  83. - (void)setState:(MJRefreshState)state
  84. {
  85. MJRefreshCheckState
  86. // 根据状态做事情
  87. if (state == MJRefreshStateIdle) {
  88. if (oldState != MJRefreshStateRefreshing) return;
  89. // 保存刷新时间
  90. [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:self.lastUpdatedTimeKey];
  91. [[NSUserDefaults standardUserDefaults] synchronize];
  92. // 恢复inset和offset
  93. [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
  94. self.scrollView.mj_insetT += self.insetTDelta;
  95. // 自动调整透明度
  96. if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0;
  97. } completion:^(BOOL finished) {
  98. self.pullingPercent = 0.0;
  99. if (self.endRefreshingCompletionBlock) {
  100. self.endRefreshingCompletionBlock();
  101. }
  102. }];
  103. } else if (state == MJRefreshStateRefreshing) {
  104. dispatch_async(dispatch_get_main_queue(), ^{
  105. [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
  106. CGFloat top = self.scrollViewOriginalInset.top + self.mj_h;
  107. // 增加滚动区域top
  108. self.scrollView.mj_insetT = top;
  109. // 设置滚动位置
  110. [self.scrollView setContentOffset:CGPointMake(0, -top) animated:NO];
  111. } completion:^(BOOL finished) {
  112. [self executeRefreshingCallback];
  113. }];
  114. });
  115. }
  116. }
  117. #pragma mark - 公共方法
  118. - (void)endRefreshing
  119. {
  120. dispatch_async(dispatch_get_main_queue(), ^{
  121. self.state = MJRefreshStateIdle;
  122. });
  123. }
  124. - (NSDate *)lastUpdatedTime
  125. {
  126. return [[NSUserDefaults standardUserDefaults] objectForKey:self.lastUpdatedTimeKey];
  127. }
  128. @end