MJRefreshHeader.m 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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. // 暂时保留
  48. if (self.window == nil) return;
  49. // sectionheader停留解决
  50. CGFloat insetT = - self.scrollView.mj_offsetY > _scrollViewOriginalInset.top ? - self.scrollView.mj_offsetY : _scrollViewOriginalInset.top;
  51. insetT = insetT > self.mj_h + _scrollViewOriginalInset.top ? self.mj_h + _scrollViewOriginalInset.top : insetT;
  52. self.scrollView.mj_insetT = insetT;
  53. self.insetTDelta = _scrollViewOriginalInset.top - insetT;
  54. return;
  55. }
  56. // 跳转到下一个控制器时,contentInset可能会变
  57. _scrollViewOriginalInset = self.scrollView.mj_inset;
  58. // 当前的contentOffset
  59. CGFloat offsetY = self.scrollView.mj_offsetY;
  60. // 头部控件刚好出现的offsetY
  61. CGFloat happenOffsetY = - self.scrollViewOriginalInset.top;
  62. // 如果是向上滚动到看不见头部控件,直接返回
  63. // >= -> >
  64. if (offsetY > happenOffsetY) return;
  65. // 普通 和 即将刷新 的临界点
  66. CGFloat normal2pullingOffsetY = happenOffsetY - self.mj_h;
  67. CGFloat pullingPercent = (happenOffsetY - offsetY) / self.mj_h;
  68. if (self.scrollView.isDragging) { // 如果正在拖拽
  69. self.pullingPercent = pullingPercent;
  70. if (self.state == MJRefreshStateIdle && offsetY < normal2pullingOffsetY) {
  71. // 转为即将刷新状态
  72. self.state = MJRefreshStatePulling;
  73. } else if (self.state == MJRefreshStatePulling && offsetY >= normal2pullingOffsetY) {
  74. // 转为普通状态
  75. self.state = MJRefreshStateIdle;
  76. }
  77. } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开
  78. // 开始刷新
  79. [self beginRefreshing];
  80. } else if (pullingPercent < 1) {
  81. self.pullingPercent = pullingPercent;
  82. }
  83. }
  84. - (void)setState:(MJRefreshState)state
  85. {
  86. MJRefreshCheckState
  87. // 根据状态做事情
  88. if (state == MJRefreshStateIdle) {
  89. if (oldState != MJRefreshStateRefreshing) return;
  90. // 保存刷新时间
  91. [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:self.lastUpdatedTimeKey];
  92. [[NSUserDefaults standardUserDefaults] synchronize];
  93. // 恢复inset和offset
  94. [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
  95. self.scrollView.mj_insetT += self.insetTDelta;
  96. // 自动调整透明度
  97. if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0;
  98. } completion:^(BOOL finished) {
  99. self.pullingPercent = 0.0;
  100. if (self.endRefreshingCompletionBlock) {
  101. self.endRefreshingCompletionBlock();
  102. }
  103. }];
  104. } else if (state == MJRefreshStateRefreshing) {
  105. MJRefreshDispatchAsyncOnMainQueue({
  106. [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
  107. CGFloat top = self.scrollViewOriginalInset.top + self.mj_h;
  108. // 增加滚动区域top
  109. self.scrollView.mj_insetT = top;
  110. // 设置滚动位置
  111. CGPoint offset = self.scrollView.contentOffset;
  112. offset.y = -top;
  113. [self.scrollView setContentOffset:offset animated:NO];
  114. } completion:^(BOOL finished) {
  115. [self executeRefreshingCallback];
  116. }];
  117. })
  118. }
  119. }
  120. #pragma mark - 公共方法
  121. - (NSDate *)lastUpdatedTime
  122. {
  123. return [[NSUserDefaults standardUserDefaults] objectForKey:self.lastUpdatedTimeKey];
  124. }
  125. - (void)setIgnoredScrollViewContentInsetTop:(CGFloat)ignoredScrollViewContentInsetTop {
  126. _ignoredScrollViewContentInsetTop = ignoredScrollViewContentInsetTop;
  127. self.mj_y = - self.mj_h - _ignoredScrollViewContentInsetTop;
  128. }
  129. @end