MJRefreshBackFooter
重寫MJRefreshComponent處理監(jiān)聽的方法
根據(jù)滾動的offset算出scrollView的滾動距離
#pragma mark - 初始化
- (void)willMoveToSuperview:(UIView *)newSuperview
{
[super willMoveToSuperview:newSuperview];
[self scrollViewContentSizeDidChange:nil];
}
#pragma mark - 實(shí)現(xiàn)父類的方法
- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
{
[super scrollViewContentOffsetDidChange:change];
// 如果正在刷新趣席,直接返回
if (self.state == MJRefreshStateRefreshing) return;
_scrollViewOriginalInset = self.scrollView.contentInset;
// 當(dāng)前的contentOffset
CGFloat currentOffsetY = self.scrollView.mj_offsetY;
// 尾部控件剛好出現(xiàn)的offsetY
CGFloat happenOffsetY = [self happenOffsetY];
// 如果是向下滾動到看不見尾部控件,直接返回
if (currentOffsetY <= happenOffsetY) return;
CGFloat pullingPercent = (currentOffsetY - happenOffsetY) / self.mj_h;
// 如果已全部加載,僅設(shè)置pullingPercent帆调,然后返回
if (self.state == MJRefreshStateNoMoreData) {
self.pullingPercent = pullingPercent;
return;
}
if (self.scrollView.isDragging) {
self.pullingPercent = pullingPercent;
// 普通 和 即將刷新 的臨界點(diǎn)
CGFloat normal2pullingOffsetY = happenOffsetY + self.mj_h;
if (self.state == MJRefreshStateIdle && currentOffsetY > normal2pullingOffsetY) {
// 轉(zhuǎn)為即將刷新狀態(tài)
self.state = MJRefreshStatePulling;
} else if (self.state == MJRefreshStatePulling && currentOffsetY <= normal2pullingOffsetY) {
// 轉(zhuǎn)為普通狀態(tài)
self.state = MJRefreshStateIdle;
}
} else if (self.state == MJRefreshStatePulling) {// 即將刷新 && 手松開
// 開始刷新
[self beginRefreshing];
} else if (pullingPercent < 1) {
self.pullingPercent = pullingPercent;
}
}
處理設(shè)置footer的frame的y犯助,如果顯示內(nèi)容超過顯示區(qū)域的高度則y在顯示內(nèi)容下面,如果顯示內(nèi)容不足以顯示占滿顯示區(qū)域,footer的y在顯示區(qū)域的下面
- (void)scrollViewContentSizeDidChange:(NSDictionary *)change
{
[super scrollViewContentSizeDidChange:change];
// 顯示內(nèi)容的高度
CGFloat contentHeight = self.scrollView.mj_contentH + self.ignoredScrollViewContentInsetBottom;
// 表格的高度牲证,可顯示區(qū)域的高度
CGFloat scrollHeight = self.scrollView.mj_h - self.scrollViewOriginalInset.top - self.scrollViewOriginalInset.bottom + self.ignoredScrollViewContentInsetBottom;
// 設(shè)置位置和尺寸
// 如果顯示內(nèi)容超過顯示區(qū)域的高度則y在顯示內(nèi)容下面研叫,如果顯示內(nèi)容不足以顯示占滿顯示區(qū)域锤窑,footer的y在顯示區(qū)域的下面
self.mj_y = MAX(contentHeight, scrollHeight);
}
根據(jù)設(shè)置的狀體進(jìn)行相應(yīng)的操作
- (void)setState:(MJRefreshState)state
{
MJRefreshCheckState
// 根據(jù)狀態(tài)來設(shè)置屬性
if (state == MJRefreshStateNoMoreData || state == MJRefreshStateIdle) {
// 刷新完畢
if (MJRefreshStateRefreshing == oldState) {
[UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
self.scrollView.mj_insetB -= self.lastBottomDelta;
// 自動調(diào)整透明度
if (self.isAutomaticallyChangeAlpha) self.alpha = 0.0;
} completion:^(BOOL finished) {
self.pullingPercent = 0.0;
if (self.endRefreshingCompletionBlock) {
self.endRefreshingCompletionBlock();
}
}];
}
CGFloat deltaH = [self heightForContentBreakView];
// 剛刷新完畢
if (MJRefreshStateRefreshing == oldState && deltaH > 0 && self.scrollView.mj_totalDataCount != self.lastRefreshCount) {
self.scrollView.mj_offsetY = self.scrollView.mj_offsetY;
}
} else if (state == MJRefreshStateRefreshing) {
// 記錄刷新前的數(shù)量
self.lastRefreshCount = self.scrollView.mj_totalDataCount;
[UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
CGFloat bottom = self.mj_h + self.scrollViewOriginalInset.bottom;
CGFloat deltaH = [self heightForContentBreakView];
if (deltaH < 0) { // 如果內(nèi)容高度小于view的高度
bottom -= deltaH;
}
self.lastBottomDelta = bottom - self.scrollView.mj_insetB;
self.scrollView.mj_insetB = bottom;
self.scrollView.mj_offsetY = [self happenOffsetY] + self.mj_h;
} completion:^(BOOL finished) {
[self executeRefreshingCallback];
}];
}
}
總結(jié):
1、對offset進(jìn)行判斷嚷炉,并且判斷isDragging
2渊啰、隨著contentSize變化調(diào)整footer的y
3、修改scrollView.contentInset
狀態(tài)間的變化申屹,對scrollView的inset進(jìn)行修改绘证,是的能看見footer或恢復(fù)成原狀,這個(gè)很特別