MJRefreshAutoFooter.m 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. //
  2. // MJRefreshAutoFooter.m
  3. // MJRefreshExample
  4. //
  5. // Created by MJ Lee on 15/4/24.
  6. // Copyright (c) 2015年 小码哥. All rights reserved.
  7. //
  8. #import "MJRefreshAutoFooter.h"
  9. @interface MJRefreshAutoFooter()
  10. /** 一个新的拖拽 */
  11. @property (nonatomic) BOOL triggerByDrag;
  12. @property (nonatomic) NSInteger leftTriggerTimes;
  13. @end
  14. @implementation MJRefreshAutoFooter
  15. #pragma mark - 初始化
  16. - (void)willMoveToSuperview:(UIView *)newSuperview
  17. {
  18. [super willMoveToSuperview:newSuperview];
  19. if (newSuperview) { // 新的父控件
  20. if (self.hidden == NO) {
  21. self.scrollView.mj_insetB += self.mj_h;
  22. }
  23. // 设置位置
  24. self.mj_y = _scrollView.mj_contentH;
  25. } else { // 被移除了
  26. if (self.hidden == NO) {
  27. self.scrollView.mj_insetB -= self.mj_h;
  28. }
  29. }
  30. }
  31. #pragma mark - 过期方法
  32. - (void)setAppearencePercentTriggerAutoRefresh:(CGFloat)appearencePercentTriggerAutoRefresh
  33. {
  34. self.triggerAutomaticallyRefreshPercent = appearencePercentTriggerAutoRefresh;
  35. }
  36. - (CGFloat)appearencePercentTriggerAutoRefresh
  37. {
  38. return self.triggerAutomaticallyRefreshPercent;
  39. }
  40. #pragma mark - 实现父类的方法
  41. - (void)prepare
  42. {
  43. [super prepare];
  44. // 默认底部控件100%出现时才会自动刷新
  45. self.triggerAutomaticallyRefreshPercent = 1.0;
  46. // 设置为默认状态
  47. self.automaticallyRefresh = YES;
  48. self.autoTriggerTimes = 1;
  49. }
  50. - (void)scrollViewContentSizeDidChange:(NSDictionary *)change
  51. {
  52. [super scrollViewContentSizeDidChange:change];
  53. // 设置位置
  54. self.mj_y = self.scrollView.mj_contentH + self.ignoredScrollViewContentInsetBottom;
  55. }
  56. - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
  57. {
  58. [super scrollViewContentOffsetDidChange:change];
  59. if (self.state != MJRefreshStateIdle || !self.automaticallyRefresh || self.mj_y == 0) return;
  60. if (_scrollView.mj_insetT + _scrollView.mj_contentH > _scrollView.mj_h) { // 内容超过一个屏幕
  61. // 这里的_scrollView.mj_contentH替换掉self.mj_y更为合理
  62. if (_scrollView.mj_offsetY >= _scrollView.mj_contentH - _scrollView.mj_h + self.mj_h * self.triggerAutomaticallyRefreshPercent + _scrollView.mj_insetB - self.mj_h) {
  63. // 防止手松开时连续调用
  64. CGPoint old = [change[@"old"] CGPointValue];
  65. CGPoint new = [change[@"new"] CGPointValue];
  66. if (new.y <= old.y) return;
  67. if (_scrollView.isDragging) {
  68. self.triggerByDrag = YES;
  69. }
  70. // 当底部刷新控件完全出现时,才刷新
  71. [self beginRefreshing];
  72. }
  73. }
  74. }
  75. - (void)scrollViewPanStateDidChange:(NSDictionary *)change
  76. {
  77. [super scrollViewPanStateDidChange:change];
  78. if (self.state != MJRefreshStateIdle) return;
  79. UIGestureRecognizerState panState = _scrollView.panGestureRecognizer.state;
  80. switch (panState) {
  81. // 手松开
  82. case UIGestureRecognizerStateEnded: {
  83. if (_scrollView.mj_insetT + _scrollView.mj_contentH <= _scrollView.mj_h) { // 不够一个屏幕
  84. if (_scrollView.mj_offsetY >= - _scrollView.mj_insetT) { // 向上拽
  85. self.triggerByDrag = YES;
  86. [self beginRefreshing];
  87. }
  88. } else { // 超出一个屏幕
  89. if (_scrollView.mj_offsetY >= _scrollView.mj_contentH + _scrollView.mj_insetB - _scrollView.mj_h) {
  90. self.triggerByDrag = YES;
  91. [self beginRefreshing];
  92. }
  93. }
  94. }
  95. break;
  96. case UIGestureRecognizerStateBegan: {
  97. [self resetTriggerTimes];
  98. }
  99. break;
  100. default:
  101. break;
  102. }
  103. }
  104. - (BOOL)unlimitedTrigger {
  105. return self.leftTriggerTimes == -1;
  106. }
  107. - (void)beginRefreshing
  108. {
  109. if (self.triggerByDrag && self.leftTriggerTimes <= 0 && !self.unlimitedTrigger) {
  110. return;
  111. }
  112. [super beginRefreshing];
  113. }
  114. - (void)setState:(MJRefreshState)state
  115. {
  116. MJRefreshCheckState
  117. if (state == MJRefreshStateRefreshing) {
  118. [self executeRefreshingCallback];
  119. } else if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) {
  120. if (self.triggerByDrag) {
  121. if (!self.unlimitedTrigger) {
  122. self.leftTriggerTimes -= 1;
  123. }
  124. self.triggerByDrag = NO;
  125. }
  126. if (MJRefreshStateRefreshing == oldState) {
  127. if (self.scrollView.pagingEnabled) {
  128. CGPoint offset = self.scrollView.contentOffset;
  129. offset.y -= self.scrollView.mj_insetB;
  130. [UIView animateWithDuration:self.slowAnimationDuration animations:^{
  131. self.scrollView.contentOffset = offset;
  132. if (self.endRefreshingAnimationBeginAction) {
  133. self.endRefreshingAnimationBeginAction();
  134. }
  135. } completion:^(BOOL finished) {
  136. if (self.endRefreshingCompletionBlock) {
  137. self.endRefreshingCompletionBlock();
  138. }
  139. }];
  140. return;
  141. }
  142. if (self.endRefreshingCompletionBlock) {
  143. self.endRefreshingCompletionBlock();
  144. }
  145. }
  146. }
  147. }
  148. - (void)resetTriggerTimes {
  149. self.leftTriggerTimes = self.autoTriggerTimes;
  150. }
  151. - (void)setHidden:(BOOL)hidden
  152. {
  153. BOOL lastHidden = self.isHidden;
  154. [super setHidden:hidden];
  155. if (!lastHidden && hidden) {
  156. self.state = MJRefreshStateIdle;
  157. self.scrollView.mj_insetB -= self.mj_h;
  158. } else if (lastHidden && !hidden) {
  159. self.scrollView.mj_insetB += self.mj_h;
  160. // 设置位置
  161. self.mj_y = _scrollView.mj_contentH;
  162. }
  163. }
  164. - (void)setAutoTriggerTimes:(NSInteger)autoTriggerTimes {
  165. _autoTriggerTimes = autoTriggerTimes;
  166. self.leftTriggerTimes = autoTriggerTimes;
  167. }
  168. @end