MJRefreshComponent.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. // MJRefreshComponent.m
  4. // MJRefreshExample
  5. //
  6. // Created by MJ Lee on 15/3/4.
  7. // Copyright (c) 2015年 小码哥. All rights reserved.
  8. //
  9. #import "MJRefreshComponent.h"
  10. #import "MJRefreshConst.h"
  11. #import "UIView+MJExtension.h"
  12. #import "UIScrollView+MJRefresh.h"
  13. @interface MJRefreshComponent()
  14. @property (strong, nonatomic) UIPanGestureRecognizer *pan;
  15. @end
  16. @implementation MJRefreshComponent
  17. #pragma mark - 初始化
  18. - (instancetype)initWithFrame:(CGRect)frame
  19. {
  20. if (self = [super initWithFrame:frame]) {
  21. // 准备工作
  22. [self prepare];
  23. // 默认是普通状态
  24. self.state = MJRefreshStateIdle;
  25. }
  26. return self;
  27. }
  28. - (void)prepare
  29. {
  30. // 基本属性
  31. self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  32. self.backgroundColor = [UIColor clearColor];
  33. }
  34. - (void)layoutSubviews
  35. {
  36. [super layoutSubviews];
  37. [self placeSubviews];
  38. }
  39. - (void)placeSubviews{}
  40. - (void)willMoveToSuperview:(UIView *)newSuperview
  41. {
  42. [super willMoveToSuperview:newSuperview];
  43. // 如果不是UIScrollView,不做任何事情
  44. if (newSuperview && ![newSuperview isKindOfClass:[UIScrollView class]]) return;
  45. // 旧的父控件移除监听
  46. [self removeObservers];
  47. if (newSuperview) { // 新的父控件
  48. // 设置宽度
  49. self.mj_w = newSuperview.mj_w;
  50. // 设置位置
  51. self.mj_x = 0;
  52. // 记录UIScrollView
  53. _scrollView = (UIScrollView *)newSuperview;
  54. // 设置永远支持垂直弹簧效果
  55. _scrollView.alwaysBounceVertical = YES;
  56. // 记录UIScrollView最开始的contentInset
  57. _scrollViewOriginalInset = _scrollView.contentInset;
  58. // 添加监听
  59. [self addObservers];
  60. }
  61. }
  62. - (void)drawRect:(CGRect)rect
  63. {
  64. [super drawRect:rect];
  65. if (self.state == MJRefreshStateWillRefresh) {
  66. // 预防view还没显示出来就调用了beginRefreshing
  67. self.state = MJRefreshStateRefreshing;
  68. }
  69. }
  70. #pragma mark - KVO监听
  71. - (void)addObservers
  72. {
  73. NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
  74. [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentOffset options:options context:nil];
  75. [self.scrollView addObserver:self forKeyPath:MJRefreshKeyPathContentSize options:options context:nil];
  76. self.pan = self.scrollView.panGestureRecognizer;
  77. [self.pan addObserver:self forKeyPath:MJRefreshKeyPathPanState options:options context:nil];
  78. }
  79. - (void)removeObservers
  80. {
  81. [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentOffset];
  82. [self.superview removeObserver:self forKeyPath:MJRefreshKeyPathContentSize];;
  83. [self.pan removeObserver:self forKeyPath:MJRefreshKeyPathPanState];
  84. self.pan = nil;
  85. }
  86. - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
  87. {
  88. // 遇到这些情况就直接返回
  89. if (!self.userInteractionEnabled) return;
  90. // 这个就算看不见也需要处理
  91. if ([keyPath isEqualToString:MJRefreshKeyPathContentSize]) {
  92. [self scrollViewContentSizeDidChange:change];
  93. }
  94. // 看不见
  95. if (self.hidden) return;
  96. if ([keyPath isEqualToString:MJRefreshKeyPathContentOffset]) {
  97. [self scrollViewContentOffsetDidChange:change];
  98. } else if ([keyPath isEqualToString:MJRefreshKeyPathPanState]) {
  99. [self scrollViewPanStateDidChange:change];
  100. }
  101. }
  102. - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change{}
  103. - (void)scrollViewContentSizeDidChange:(NSDictionary *)change{}
  104. - (void)scrollViewPanStateDidChange:(NSDictionary *)change{}
  105. #pragma mark - 公共方法
  106. #pragma mark 设置回调对象和回调方法
  107. - (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action
  108. {
  109. self.refreshingTarget = target;
  110. self.refreshingAction = action;
  111. }
  112. #pragma mark 进入刷新状态
  113. - (void)beginRefreshing
  114. {
  115. [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
  116. self.alpha = 1.0;
  117. }];
  118. self.pullingPercent = 1.0;
  119. // 只要正在刷新,就完全显示
  120. if (self.window) {
  121. self.state = MJRefreshStateRefreshing;
  122. } else {
  123. self.state = MJRefreshStateWillRefresh;
  124. // 刷新(预防从另一个控制器回到这个控制器的情况,回来要重新刷新一下)
  125. [self setNeedsDisplay];
  126. }
  127. }
  128. #pragma mark 结束刷新状态
  129. - (void)endRefreshing
  130. {
  131. self.state = MJRefreshStateIdle;
  132. }
  133. #pragma mark 是否正在刷新
  134. - (BOOL)isRefreshing
  135. {
  136. return self.state == MJRefreshStateRefreshing || self.state == MJRefreshStateWillRefresh;
  137. }
  138. #pragma mark 自动切换透明度
  139. - (void)setAutoChangeAlpha:(BOOL)autoChangeAlpha
  140. {
  141. self.automaticallyChangeAlpha = autoChangeAlpha;
  142. }
  143. - (BOOL)isAutoChangeAlpha
  144. {
  145. return self.isAutomaticallyChangeAlpha;
  146. }
  147. - (void)setAutomaticallyChangeAlpha:(BOOL)automaticallyChangeAlpha
  148. {
  149. _automaticallyChangeAlpha = automaticallyChangeAlpha;
  150. if (self.isRefreshing) return;
  151. if (automaticallyChangeAlpha) {
  152. self.alpha = self.pullingPercent;
  153. } else {
  154. self.alpha = 1.0;
  155. }
  156. }
  157. #pragma mark 根据拖拽进度设置透明度
  158. - (void)setPullingPercent:(CGFloat)pullingPercent
  159. {
  160. _pullingPercent = pullingPercent;
  161. if (self.isRefreshing) return;
  162. if (self.isAutomaticallyChangeAlpha) {
  163. self.alpha = pullingPercent;
  164. }
  165. }
  166. #pragma mark - 内部方法
  167. - (void)executeRefreshingCallback
  168. {
  169. dispatch_async(dispatch_get_main_queue(), ^{
  170. if (self.refreshingBlock) {
  171. self.refreshingBlock();
  172. }
  173. if ([self.refreshingTarget respondsToSelector:self.refreshingAction]) {
  174. MJRefreshMsgSend(MJRefreshMsgTarget(self.refreshingTarget), self.refreshingAction, self);
  175. }
  176. });
  177. }
  178. @end
  179. @implementation UILabel(MJRefresh)
  180. + (instancetype)label
  181. {
  182. UILabel *label = [[self alloc] init];
  183. label.font = MJRefreshLabelFont;
  184. label.textColor = MJRefreshLabelTextColor;
  185. label.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  186. label.textAlignment = NSTextAlignmentCenter;
  187. label.backgroundColor = [UIColor clearColor];
  188. return label;
  189. }
  190. @end