M了个J 11 éve
szülő
commit
c6f8c179dc

+ 10 - 0
MJRefreshExample/MJRefreshExample.xcodeproj/project.pbxproj

@@ -10,6 +10,8 @@
 		2D1D8FB21935C0CD0019D689 /* UIScrollView+MJRefresh.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D1D8FB11935C0CD0019D689 /* UIScrollView+MJRefresh.m */; };
 		2D1D8FB51935EABD0019D689 /* UIView+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D1D8FB41935EABD0019D689 /* UIView+Extension.m */; };
 		2D1D8FB81935EACA0019D689 /* UIScrollView+Extension.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D1D8FB71935EACA0019D689 /* UIScrollView+Extension.m */; };
+		2D1D8FBC19360E040019D689 /* MJTestViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2D1D8FBA19360E040019D689 /* MJTestViewController.m */; };
+		2D1D8FBD19360E040019D689 /* MJTestViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2D1D8FBB19360E040019D689 /* MJTestViewController.xib */; };
 		2D9CAF6B192FAD750011F500 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D9CAF6A192FAD750011F500 /* Foundation.framework */; };
 		2D9CAF6D192FAD750011F500 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D9CAF6C192FAD750011F500 /* CoreGraphics.framework */; };
 		2D9CAF6F192FAD750011F500 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2D9CAF6E192FAD750011F500 /* UIKit.framework */; };
@@ -51,6 +53,9 @@
 		2D1D8FB41935EABD0019D689 /* UIView+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Extension.m"; sourceTree = "<group>"; };
 		2D1D8FB61935EACA0019D689 /* UIScrollView+Extension.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+Extension.h"; sourceTree = "<group>"; };
 		2D1D8FB71935EACA0019D689 /* UIScrollView+Extension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+Extension.m"; sourceTree = "<group>"; };
+		2D1D8FB919360E040019D689 /* MJTestViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MJTestViewController.h; sourceTree = "<group>"; };
+		2D1D8FBA19360E040019D689 /* MJTestViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MJTestViewController.m; sourceTree = "<group>"; };
+		2D1D8FBB19360E040019D689 /* MJTestViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MJTestViewController.xib; sourceTree = "<group>"; };
 		2D9CAF67192FAD750011F500 /* MJRefreshExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MJRefreshExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
 		2D9CAF6A192FAD750011F500 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
 		2D9CAF6C192FAD750011F500 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
@@ -203,6 +208,9 @@
 				2D9CAFA6192FAD9F0011F500 /* MJSampleIndexViewController.m */,
 				2D9CAFA7192FAD9F0011F500 /* MJTableViewController.h */,
 				2D9CAFA8192FAD9F0011F500 /* MJTableViewController.m */,
+				2D1D8FB919360E040019D689 /* MJTestViewController.h */,
+				2D1D8FBA19360E040019D689 /* MJTestViewController.m */,
+				2D1D8FBB19360E040019D689 /* MJTestViewController.xib */,
 			);
 			path = Controller;
 			sourceTree = "<group>";
@@ -329,6 +337,7 @@
 				2D9CAF83192FAD750011F500 /* Images.xcassets in Resources */,
 				2D9CAF75192FAD750011F500 /* InfoPlist.strings in Resources */,
 				2D9CAFC2192FAD9F0011F500 /* MJRefresh.bundle in Resources */,
+				2D1D8FBD19360E040019D689 /* MJTestViewController.xib in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -357,6 +366,7 @@
 				2D9CAFC6192FAD9F0011F500 /* MJRefreshHeaderView.m in Sources */,
 				2D9CAFBB192FAD9F0011F500 /* MJCollectionViewController.m in Sources */,
 				2D9CAFC1192FAD9F0011F500 /* MJAppDelegate.m in Sources */,
+				2D1D8FBC19360E040019D689 /* MJTestViewController.m in Sources */,
 				2D1D8FB21935C0CD0019D689 /* UIScrollView+MJRefresh.m in Sources */,
 				2D9CAFC3192FAD9F0011F500 /* MJRefreshBaseView.m in Sources */,
 				2D9CAFC0192FAD9F0011F500 /* main.m in Sources */,

BIN
MJRefreshExample/MJRefreshExample.xcodeproj/project.xcworkspace/xcuserdata/mj.xcuserdatad/UserInterfaceState.xcuserstate


+ 7 - 0
MJRefreshExample/MJRefreshExample/Classes/Controller/MJCollectionViewController.m

@@ -16,6 +16,7 @@
 #define MJRandomColor [UIColor colorWithRed:arc4random_uniform(255)/255.0 green:arc4random_uniform(255)/255.0 blue:arc4random_uniform(255)/255.0 alpha:1]
 
 #import "MJCollectionViewController.h"
+#import "MJTestViewController.h"
 #import "MJRefresh.h"
 
 @interface MJCollectionViewController ()
@@ -145,4 +146,10 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell
     cell.backgroundColor = self.fakeColors[indexPath.row];
     return cell;
 }
+
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    MJTestViewController *test = [[MJTestViewController alloc] init];
+    [self.navigationController pushViewController:test animated:YES];
+}
 @end

+ 6 - 0
MJRefreshExample/MJRefreshExample/Classes/Controller/MJTableViewController.m

@@ -9,6 +9,7 @@
  具体用法:查看MJRefresh.h
  */
 #import "MJTableViewController.h"
+#import "MJTestViewController.h"
 #import "MJRefresh.h"
 
 NSString *const MJTableViewCellIdentifier = @"Cell";
@@ -126,4 +127,9 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
     return cell;
 }
 
+- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    MJTestViewController *test = [[MJTestViewController alloc] init];
+    [self.navigationController pushViewController:test animated:YES];
+}
 @end

+ 13 - 0
MJRefreshExample/MJRefreshExample/Classes/Controller/MJTestViewController.h

@@ -0,0 +1,13 @@
+//
+//  MJTestViewController.h
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 14-5-28.
+//  Copyright (c) 2014年 itcast. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface MJTestViewController : UIViewController
+
+@end

+ 24 - 0
MJRefreshExample/MJRefreshExample/Classes/Controller/MJTestViewController.m

@@ -0,0 +1,24 @@
+//
+//  MJTestViewController.m
+//  MJRefreshExample
+//
+//  Created by MJ Lee on 14-5-28.
+//  Copyright (c) 2014年 itcast. All rights reserved.
+//
+
+#import "MJTestViewController.h"
+
+@interface MJTestViewController ()
+
+@end
+
+@implementation MJTestViewController
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    
+    self.title = @"测试控制器";
+}
+
+@end

+ 21 - 0
MJRefreshExample/MJRefreshExample/Classes/Controller/MJTestViewController.xib

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="5023" systemVersion="13A603" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="3733"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MJTestViewController">
+            <connections>
+                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
+            <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+            <simulatedStatusBarMetrics key="simulatedStatusBarMetrics"/>
+            <simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina4"/>
+        </view>
+    </objects>
+</document>

+ 4 - 47
MJRefreshExample/MJRefreshExample/MJRefresh/MJRefreshBaseView.m

@@ -18,13 +18,6 @@ @interface  MJRefreshBaseView()
     __weak UIImageView *_arrowImage;
     __weak UIActivityIndicatorView *_activityView;
 }
-/**
- 交给子类去实现
- */
-// 合理的Y值
-- (CGFloat)validY;
-// view的类型
-- (MJRefreshViewType)viewType;
 @end
 
 @implementation MJRefreshBaseView
@@ -156,45 +149,11 @@ - (void)endRefreshing
     });
 }
 
-#pragma mark - 监听UIScrollView的contentOffset属性
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
-{
-    // 不是contentOffset就直接返回
-    if (![MJRefreshContentOffset isEqualToString:keyPath]) return;
-    
-    // 不能跟用户交互就直接返回
-    if (!self.userInteractionEnabled || self.alpha <= 0.01 || self.hidden) return;
-    
-    // 如果正在刷新,直接返回
-    if (self.state == MJRefreshStateRefreshing) return;
-    
-    // scrollView所滚动的Y值 * 控件的类型(头部控件是-1,尾部控件是1)
-    CGFloat offsetY = self.scrollView.contentOffsetY * self.viewType;
-    CGFloat validY = self.validY;
-    if (offsetY <= validY) return;
-    
-    if (self.scrollView.isDragging) {
-        CGFloat validOffsetY = validY + self.frame.size.height;
-        if (self.state == MJRefreshStatePulling && offsetY <= validOffsetY) {
-            // 转为普通状态
-            self.state = MJRefreshStateNormal;
-        } else if (self.state == MJRefreshStateNormal && offsetY > validOffsetY) {
-            // 转为即将刷新状态
-            self.state = MJRefreshStatePulling;
-        }
-    } else { // 即将刷新 && 手松开
-        if (self.state == MJRefreshStatePulling) {
-            // 开始刷新
-            self.state = MJRefreshStateRefreshing;
-        }
-    }
-}
-
 #pragma mark - 设置状态
 - (void)setState:(MJRefreshState)state
 {
+    // 0.存储当前的contentInset
     if (self.state != MJRefreshStateRefreshing) {
-        // 存储当前的contentInset
         _scrollViewOriginalInset = self.scrollView.contentInset;
     }
     
@@ -207,6 +166,7 @@ - (void)setState:(MJRefreshState)state
         {
             // 显示箭头
             self.arrowImage.hidden = NO;
+            
             // 停止转圈圈
             [self.activityView stopAnimating];
 			break;
@@ -216,11 +176,11 @@ - (void)setState:(MJRefreshState)state
             break;
             
 		case MJRefreshStateRefreshing:
+        {
             // 开始转圈圈
 			[self.activityView startAnimating];
             // 隐藏箭头
 			self.arrowImage.hidden = YES;
-            self.arrowImage.transform = CGAffineTransformIdentity;
             
             // 回调
             if ([self.beginRefreshingTaget respondsToSelector:self.beginRefreshingAction]) {
@@ -231,6 +191,7 @@ - (void)setState:(MJRefreshState)state
                 self.beginRefreshingCallback();
             }
 			break;
+        }
         default:
             break;
 	}
@@ -238,8 +199,4 @@ - (void)setState:(MJRefreshState)state
     // 3.存储状态
     _state = state;
 }
-
-#pragma mark - 随便实现
-- (CGFloat)validY { return 0;}
-- (MJRefreshViewType)viewType {return MJRefreshViewTypeHeader;}
 @end

+ 83 - 59
MJRefreshExample/MJRefreshExample/MJRefresh/MJRefreshFooterView.m

@@ -42,12 +42,12 @@ - (void)willMoveToSuperview:(UIView *)newSuperview
         [newSuperview addObserver:self forKeyPath:MJRefreshContentSize options:NSKeyValueObservingOptionNew context:nil];
         
         // 重新调整frame
-        [self adjustFrame];
+        [self adjustFrameWithContentSize];
     }
 }
 
 #pragma mark 重写调整frame
-- (void)adjustFrame
+- (void)adjustFrameWithContentSize
 {
     // 内容的高度
     CGFloat contentHeight = self.scrollView.contentSizeHeight;
@@ -60,92 +60,121 @@ - (void)adjustFrame
 #pragma mark 监听UIScrollView的属性
 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 {
-    [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
-    
-    // 不是contentSize,直接返回
-    if (![MJRefreshContentSize isEqualToString:keyPath]) return;
-    
     // 不能跟用户交互,直接返回
     if (!self.userInteractionEnabled || self.alpha <= 0.01 || self.hidden) return;
     
-    // 如果正在刷新,直接返回
-    if (self.state == MJRefreshStateRefreshing) return;
+    if ([MJRefreshContentSize isEqualToString:keyPath]) {
+        // 调整frame
+        [self adjustFrameWithContentSize];
+    } else if ([MJRefreshContentOffset isEqualToString:keyPath]) {
+#warning 这个返回一定要放这个位置
+        // 如果正在刷新,直接返回
+        if (self.state == MJRefreshStateRefreshing) return;
+        
+        // 调整状态
+        [self adjustStateWithContentOffset];
+    }
+}
+
+/**
+ *  调整状态
+ */
+- (void)adjustStateWithContentOffset
+{
+    // 当前的contentOffset
+    CGFloat currentOffsetY = self.scrollView.contentOffsetY;
+    // 尾部控件刚好出现的offsetY
+    CGFloat happenOffsetY = [self happenOffsetY];
+    
+    // 如果是向下滚动到看不见尾部控件,直接返回
+    if (currentOffsetY <= happenOffsetY) return;
     
-    // 调整frame
-    [self adjustFrame];
+    if (self.scrollView.isDragging) {
+        // 普通 和 即将刷新 的临界点
+        CGFloat normal2pullingOffsetY = happenOffsetY + self.height;
+        
+        if (self.state == MJRefreshStateNormal && currentOffsetY > normal2pullingOffsetY) {
+            // 转为即将刷新状态
+            self.state = MJRefreshStatePulling;
+        } else if (self.state == MJRefreshStatePulling && currentOffsetY <= normal2pullingOffsetY) {
+            // 转为普通状态
+            self.state = MJRefreshStateNormal;
+        }
+    } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开
+        // 开始刷新
+        self.state = MJRefreshStateRefreshing;
+    }
 }
 
 #pragma mark - 状态相关
 #pragma mark 设置状态
 - (void)setState:(MJRefreshState)state
 {
+    // 1.一样的就直接返回
     if (self.state == state) return;
+    
+    // 2.保存旧状态
     MJRefreshState oldState = self.state;
     
+    // 3.调用父类方法
     [super setState:state];
     
+    // 4.根据状态来设置属性
 	switch (state)
     {
-		case MJRefreshStatePulling:
-        {
-            self.statusLabel.text = MJRefreshFooterReleaseToRefresh;
-            
-            [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
-                self.arrowImage.transform = CGAffineTransformIdentity;
-                UIEdgeInsets inset = self.scrollView.contentInset;
-                inset.bottom = self.scrollViewOriginalInset.bottom;
-                self.scrollView.contentInset = inset;
-            }];
-			break;
-        }
-            
 		case MJRefreshStateNormal:
         {
+            // 设置文字
             self.statusLabel.text = MJRefreshFooterPullToRefresh;
             
-            // 刚刷新完毕
-            CGFloat animDuration = MJRefreshSlowAnimationDuration;
-            CGFloat deltaH = [self contentBreakView];
-            CGPoint tempOffset;
+            // 刷新完毕
+            if (MJRefreshStateRefreshing == oldState) {
+                self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
+                [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
+                    self.scrollView.contentInsetBottom = self.scrollViewOriginalInset.bottom;
+                }];
+            } else {
+                // 执行动画
+                [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+                    self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
+                }];
+            }
             
+            CGFloat deltaH = [self heightForContentBreakView];
             int currentCount = [self totalDataCountInScrollView];
+            // 刚刷新完毕
             if (MJRefreshStateRefreshing == oldState && deltaH > 0 && currentCount != self.lastRefreshCount) {
-                tempOffset = self.scrollView.contentOffset;
-                animDuration = 0;
+                self.scrollView.contentOffsetY = self.scrollView.contentOffsetY;
             }
+			break;
+        }
             
-            [UIView animateWithDuration:animDuration animations:^{
-                UIEdgeInsets inset = self.scrollView.contentInset;
-                inset.bottom = self.scrollViewOriginalInset.bottom;
-                self.scrollView.contentInset = inset;
-            }];
+		case MJRefreshStatePulling:
+        {
+            // 设置文字
+            self.statusLabel.text = MJRefreshFooterReleaseToRefresh;
             
-            [UIView animateWithDuration:animDuration ? MJRefreshFastAnimationDuration : animDuration animations:^{
-                self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
+            [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+                self.arrowImage.transform = CGAffineTransformIdentity;
             }];
-            
-            if (animDuration == 0) {
-                self.scrollView.contentOffset = tempOffset;
-            }
 			break;
         }
             
         case MJRefreshStateRefreshing:
         {
+            // 设置文字
+            self.statusLabel.text = MJRefreshFooterRefreshing;
+            
             // 记录刷新前的数量
             self.lastRefreshCount = [self totalDataCountInScrollView];
-            self.statusLabel.text = MJRefreshFooterRefreshing;
             
             [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
-                self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
-                UIEdgeInsets inset = self.scrollView.contentInset;
-                CGFloat bottom = self.frame.size.height + self.scrollViewOriginalInset.bottom;
-                CGFloat deltaH = [self contentBreakView];
+                CGFloat bottom = self.height + self.scrollViewOriginalInset.bottom;
+                CGFloat deltaH = [self heightForContentBreakView];
                 if (deltaH < 0) { // 如果内容高度小于view的高度
                     bottom -= deltaH;
                 }
-                inset.bottom = bottom;
-                self.scrollView.contentInset = inset;
+                self.scrollView.contentInsetBottom = bottom;
             }];
 			break;
         }
@@ -155,7 +184,6 @@ - (void)setState:(MJRefreshState)state
 	}
 }
 
-
 - (int)totalDataCountInScrollView
 {
     int totalCount = 0;
@@ -176,27 +204,23 @@ - (int)totalDataCountInScrollView
 }
 
 #pragma mark 获得scrollView的内容 超出 view 的高度
-- (CGFloat)contentBreakView
+- (CGFloat)heightForContentBreakView
 {
     CGFloat h = self.scrollView.frame.size.height - self.scrollViewOriginalInset.bottom - self.scrollViewOriginalInset.top;
     return self.scrollView.contentSize.height - h;
 }
 
 #pragma mark - 在父类中用得上
-// 合理的Y值(刚好看到上拉刷新控件时的contentOffset.y,取相反数)
-- (CGFloat)validY
+/**
+ *  刚好看到上拉刷新控件时的contentOffset.y
+ */
+- (CGFloat)happenOffsetY
 {
-    CGFloat deltaH = [self contentBreakView];
+    CGFloat deltaH = [self heightForContentBreakView];
     if (deltaH > 0) {
         return deltaH - self.scrollViewOriginalInset.top;
     } else {
         return - self.scrollViewOriginalInset.top;
     }
 }
-
-// view的类型
-- (int)viewType
-{
-    return MJRefreshViewTypeFooter;
-}
 @end

+ 69 - 42
MJRefreshExample/MJRefreshExample/MJRefresh/MJRefreshHeaderView.m

@@ -111,6 +111,49 @@ - (void)updateTimeLabel
     // 3.显示日期
     self.lastUpdateTimeLabel.text = [NSString stringWithFormat:@"最后更新:%@", time];
 }
+#pragma mark - 监听UIScrollView的contentOffset属性
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+    // 不能跟用户交互就直接返回
+    if (!self.userInteractionEnabled || self.alpha <= 0.01 || self.hidden) return;
+
+    // 如果正在刷新,直接返回
+    if (self.state == MJRefreshStateRefreshing) return;
+
+    if ([MJRefreshContentOffset isEqualToString:keyPath]) {
+        [self adjustStateWithContentOffset];
+    }
+}
+
+/**
+ *  调整状态
+ */
+- (void)adjustStateWithContentOffset
+{
+    // 当前的contentOffset
+    CGFloat currentOffsetY = self.scrollView.contentOffsetY;
+    // 头部控件刚好出现的offsetY
+    CGFloat happenOffsetY = - self.scrollViewOriginalInset.top;
+    
+    // 如果是向上滚动到看不见头部控件,直接返回
+    if (currentOffsetY >= happenOffsetY) return;
+    
+    if (self.scrollView.isDragging) {
+        // 普通 和 即将刷新 的临界点
+        CGFloat normal2pullingOffsetY = happenOffsetY - self.height;
+        
+        if (self.state == MJRefreshStateNormal && currentOffsetY < normal2pullingOffsetY) {
+            // 转为即将刷新状态
+            self.state = MJRefreshStatePulling;
+        } else if (self.state == MJRefreshStatePulling && currentOffsetY >= normal2pullingOffsetY) {
+            // 转为普通状态
+            self.state = MJRefreshStateNormal;
+        }
+    } else if (self.state == MJRefreshStatePulling) {// 即将刷新 && 手松开
+        // 开始刷新
+        self.state = MJRefreshStateRefreshing;
+    }
+}
 
 #pragma mark 设置状态
 - (void)setState:(MJRefreshState)state
@@ -126,56 +169,53 @@ - (void)setState:(MJRefreshState)state
     
     // 4.根据状态执行不同的操作
 	switch (state) {
-		case MJRefreshStatePulling: // 松开可立即刷新
-        {
-            // 设置文字
-            self.statusLabel.text = MJRefreshHeaderReleaseToRefresh;
-            // 执行动画
-            [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
-                self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
-                UIEdgeInsets inset = self.scrollView.contentInset;
-                inset.top = self.scrollViewOriginalInset.top;
-                self.scrollView.contentInset = inset;
-            }];
-			break;
-        }
-            
 		case MJRefreshStateNormal: // 下拉可以刷新
         {
             // 设置文字
 			self.statusLabel.text = MJRefreshHeaderPullToRefresh;
-            // 执行动画
-            [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
-                self.arrowImage.transform = CGAffineTransformIdentity;
-            }];
-            
-            [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
-                UIEdgeInsets inset = self.scrollView.contentInset;
-                inset.top = self.scrollViewOriginalInset.top;
-                self.scrollView.contentInset = inset;
-            }];
             
             // 刷新完毕
             if (MJRefreshStateRefreshing == oldState) {
+                self.arrowImage.transform = CGAffineTransformIdentity;
                 // 保存刷新时间
                 self.lastUpdateTime = [NSDate date];
+                
+                [UIView animateWithDuration:MJRefreshSlowAnimationDuration animations:^{
+                    self.scrollView.contentInsetTop = self.scrollViewOriginalInset.top;
+                }];
+            } else {
+                // 执行动画
+                [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+                    self.arrowImage.transform = CGAffineTransformIdentity;
+                }];
             }
 			break;
         }
             
+		case MJRefreshStatePulling: // 松开可立即刷新
+        {
+            // 设置文字
+            self.statusLabel.text = MJRefreshHeaderReleaseToRefresh;
+            // 执行动画
+            [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
+                self.arrowImage.transform = CGAffineTransformMakeRotation(M_PI);
+            }];
+			break;
+        }
+            
 		case MJRefreshStateRefreshing: // 正在刷新中
         {
             // 设置文字
             self.statusLabel.text = MJRefreshHeaderRefreshing;
+            
             // 执行动画
             [UIView animateWithDuration:MJRefreshFastAnimationDuration animations:^{
-                self.arrowImage.transform = CGAffineTransformIdentity;
                 // 1.增加65的滚动区域
-                UIEdgeInsets inset = self.scrollView.contentInset;
-                inset.top = self.scrollViewOriginalInset.top + MJRefreshViewHeight;
-                self.scrollView.contentInset = inset;
+                CGFloat top = self.scrollViewOriginalInset.top + self.height;
+                self.scrollView.contentInsetTop = top;
+                
                 // 2.设置滚动位置
-                self.scrollView.contentOffset = CGPointMake(0, - self.scrollViewOriginalInset.top - MJRefreshViewHeight);
+                self.scrollView.contentOffsetY = - top;
             }];
 			break;
         }
@@ -184,17 +224,4 @@ - (void)setState:(MJRefreshState)state
             break;
 	}
 }
-
-#pragma mark - 在父类中用得上
-// 合理的Y值(刚好看到下拉刷新控件时的contentOffset.y,取相反数)
-- (CGFloat)validY
-{
-    return self.scrollViewOriginalInset.top;
-}
-
-// view的类型
-- (int)viewType
-{
-    return MJRefreshViewTypeHeader;
-}
 @end