上拉加载下拉刷新控件WaterRefreshLoadMoreView

简介:

上拉加载下拉刷新控件WaterRefreshLoadMoreView

效果:

源码:

//
//  SRSlimeView
//  @author  SR
//  Modified by JunHan on 13-9-18.
//

#import <UIKit/UIKit.h>

#define kStartTo    0.7f
#define kEndTo      0.15f
#define kAnimationInterval  (1.0f / 50.0f)

NS_INLINE CGFloat distansBetween(CGPoint p1 , CGPoint p2) {
    return sqrtf((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}

typedef enum {
    SRSlimeStateNormal,
    SRSlimeStateShortening,
    SRSlimeStateMiss
} SRSlimeState;

@class SRSlimeView;

@interface SRSlimeView : UIView

@property (nonatomic, assign)   CGPoint startPoint, toPoint;
@property (nonatomic, assign)   CGFloat viscous;    //default 55
@property (nonatomic, assign)   CGFloat radius;     //default 13
@property (nonatomic, assign)   CGFloat lineWith;
@property (nonatomic, assign)   CGFloat shadowBlur;

@property (nonatomic, strong)   UIColor *bodyColor, *skinColor;
@property (nonatomic, strong)   UIColor *shadowColor;

@property (nonatomic, assign)   SRSlimeState state;

- (void)setPullApartTarget:(id)target action:(SEL)action;

@end

SRSlimeView.h


//
//  SRSlimeView
//  @author  SR
//  Modified by JunHan on 13-9-18.
//

#import "SRSlimeView.h"
#import <QuartzCore/QuartzCore.h>

NS_INLINE CGPoint pointLineToArc(CGPoint center, CGPoint p2, float angle, CGFloat radius) {
    float angleS = atan2f(p2.y - center.y, p2.x - center.x);
    float angleT = angleS + angle;
    float x = radius * cosf(angleT);
    float y = radius * sinf(angleT);
    return CGPointMake(x + center.x, y + center.y);
}

@implementation SRSlimeView {
    __weak id  _target;
    SEL _action;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
        _toPoint = _startPoint = CGPointMake(frame.size.width / 2,
                                             frame.size.height / 2);
        _viscous = 45.0f; // 拉扯长度
        _radius = 17.0f;  // 拉扯物体半径
        _bodyColor = [[UIColor grayColor] colorWithAlphaComponent:0.45f];
        _skinColor = [[UIColor blackColor] colorWithAlphaComponent:0.12f];
        _lineWith = 1.0;
        _shadowBlur = 4;
        _shadowColor = [[UIColor grayColor] colorWithAlphaComponent:0.7f];
    }
    return self;
}

- (void)setLineWith:(CGFloat)lineWith
{
    _lineWith = lineWith;
    [self setNeedsDisplay];
}

- (void)setStartPoint:(CGPoint)startPoint
{
    if (CGPointEqualToPoint(_startPoint, startPoint))
        return;
    if (_state == SRSlimeStateNormal) {
        _startPoint = startPoint;
        [self setNeedsDisplay];
    }
}

- (void)setToPoint:(CGPoint)toPoint
{
    if (CGPointEqualToPoint(_toPoint, toPoint))
        return;
    if (_state == SRSlimeStateNormal) {
        _toPoint = toPoint;
        [self setNeedsDisplay];
    }
}

- (UIBezierPath*)bodyPath:(CGFloat)startRadius end:(CGFloat)endRadius percent:(float)percent
{
    UIBezierPath *path = [[UIBezierPath alloc] init];
    float angle1 = M_PI/3 + (M_PI/6) * percent;
    CGPoint sp1 = pointLineToArc(_startPoint, _toPoint, angle1, startRadius),
    sp2 = pointLineToArc(_startPoint, _toPoint, -angle1, startRadius),
    ep1 = pointLineToArc(_toPoint, _startPoint, M_PI/2, endRadius),
    ep2 = pointLineToArc(_toPoint, _startPoint, -M_PI/2, endRadius);
#define kMiddleP  0.6
    CGPoint mp1 = CGPointMake(sp2.x*kMiddleP + ep1.x*(1-kMiddleP), sp2.y*kMiddleP + ep1.y*(1-kMiddleP)),
    mp2 = CGPointMake(sp1.x*kMiddleP + ep2.x*(1-kMiddleP), sp1.y*kMiddleP + ep2.y*(1-kMiddleP)),
    mm = CGPointMake((mp1.x + mp2.x)/2, (mp1.y + mp2.y)/2);
    float p = distansBetween(mp1, mp2) / 2 / endRadius * (0.9 + percent/10);
    mp1 = CGPointMake((mp1.x - mm.x)/p + mm.x, (mp1.y - mm.y)/p + mm.y);
    mp2 = CGPointMake((mp2.x - mm.x)/p + mm.x, (mp2.y - mm.y)/p + mm.y);
    [path moveToPoint:sp1];
    float angleS = atan2f(_toPoint.y - _startPoint.y,
                          _toPoint.x - _startPoint.x);
    [path addArcWithCenter:_startPoint
                    radius:startRadius
                startAngle:angleS + angle1
                  endAngle:angleS + M_PI*2 - angle1
                 clockwise:YES];
    
    [path addQuadCurveToPoint:ep1
                 controlPoint:mp1];
    angleS = atan2f(_startPoint.y - _toPoint.y,
                    _startPoint.x - _toPoint.x);
    [path addArcWithCenter:_toPoint
                    radius:endRadius
                startAngle:angleS + M_PI/2
                  endAngle:angleS + M_PI*3/2
                 clockwise:YES];
    [path addQuadCurveToPoint:sp1
                 controlPoint:mp2];
    
    return path;
}

- (void)drawRect:(CGRect)rect
{
    switch (_state) {
        case SRSlimeStateNormal:
        {
            float percent = 1 - distansBetween(_startPoint , _toPoint) / _viscous;
            if (percent == 1) {
                CGContextRef context = UIGraphicsGetCurrentContext();
                UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(_startPoint.x - _radius, _startPoint.y - _radius, 2*_radius, 2*_radius)
                                      
                                                                cornerRadius:_radius];
                [self setContext:context path:path];
                CGContextDrawPath(context, kCGPathFillStroke);
            }else {
                CGFloat startRadius = _radius * (kStartTo + (1 - kStartTo) * percent);
                CGFloat endRadius = _radius * (kEndTo + (1 - kEndTo) * percent);
                CGContextRef context = UIGraphicsGetCurrentContext();
                // build curve path
                UIBezierPath *path = [self bodyPath:startRadius
                                                end:endRadius
                                            percent:percent];
                [self setContext:context path:path];
                CGContextDrawPath(context, kCGPathFillStroke);
                if (percent <= 0) {
                    _state = SRSlimeStateShortening;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
                    [_target performSelector:_action
                                  withObject:self];
#pragma clang diagnostic pop
                    [self performSelector:@selector(scaling)
                               withObject:nil
                               afterDelay:kAnimationInterval
                                  inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
                }
            }
        }
            break;
        case SRSlimeStateShortening:
        {
            // back shortneing
            _toPoint = CGPointMake((_toPoint.x - _startPoint.x) * 0.8 + _startPoint.x,
                                   (_toPoint.y - _startPoint.y) * 0.8 + _startPoint.y);
            float p = distansBetween(_startPoint, _toPoint) / _viscous;
            float percent = 1 - p;
            float r = _radius * p;
            
            if (p > 0.01) {
                CGFloat startRadius = r * (kStartTo + (1 - kStartTo) * percent);
                CGContextRef context = UIGraphicsGetCurrentContext();
                
                CGFloat endRadius = r * (kEndTo + (1 - kEndTo) * percent) * (1 + percent / 2);
                UIBezierPath *path = [self bodyPath:startRadius
                                                end:endRadius
                                            percent:percent];
                [self setContext:context path:path];
                CGContextDrawPath(context, kCGPathFillStroke);
            }else {
                self.hidden = YES;
                _state = SRSlimeStateMiss;
            }
        }
            break;
        default:
            break;
    }
}

- (void)setContext:(CGContextRef)context path:(UIBezierPath *)path {
    if (self.shadowColor) {
        CGContextSetShadowWithColor(context, CGSizeZero, self.shadowBlur, self.shadowColor.CGColor);
    }
    CGContextSetFillColorWithColor(context, self.bodyColor.CGColor); 
    CGContextSetLineWidth(context, self.lineWith);
    CGContextSetStrokeColorWithColor(context, self.skinColor.CGColor);
    CGContextAddPath(context, path.CGPath);
}

- (void)scaling
{
    if (_state == SRSlimeStateShortening) {
        [self setNeedsDisplay];
        [self performSelector:@selector(scaling)
                   withObject:nil
                   afterDelay:kAnimationInterval
                      inModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
    }
}

- (void)setPullApartTarget:(id)target action:(SEL)action
{
    _target = target;
    _action = action;
}

- (void)setHidden:(BOOL)hidden
{
    [super setHidden:hidden];
    if (!hidden) {
        self.layer.transform = CATransform3DIdentity;
        [self setNeedsDisplay];
    }
}

- (void)setState:(SRSlimeState)state
{
    _state = state;
    [NSObject cancelPreviousPerformRequestsWithTarget:self
                                             selector:@selector(scaling)
                                               object:nil];
}

@end

SRSlimeView.m


/**
 *  WaterRefreshLoadMoreView.h
 *  A refresh view looks like UIRefreshControl and have loadMore function
 *  (水滴下拉刷新,上拉加载)
 *
 *  使用方法:(可设置type类型,默认是下拉上拉都有)
 *      1.  直接initWithType创建,然后将它的scrollView赋值,别忘了在使用它的ScrollView 或者 VC的dealloc
 *          中调用这个 deallocWithCloseConnect 方法
 *
 *  Created by 覃俊涵 on 13-9-18. All rights reserved.
 **/

#import <UIKit/UIKit.h>
#import "SRSlimeView.h"

typedef enum{
    WaterRefreshTypeRefreshAndLoadMore,//含下拉上拉(default)
    WaterRefreshTypeOnlyRefresh,       //仅下拉刷新
    WaterRefreshTypeOnlyLoadMore,      //仅加载更多
    WaterRefreshTypeNone
}WaterViewType;

@protocol WaterRefreshDelegate;
@protocol WaterLoadMoreDelegate;

@interface WaterRefreshLoadMoreView : UIView

@property (nonatomic, weak) UIScrollView *scrollView;
@property (nonatomic, assign) WaterViewType type;

// 水下拉的view
@property (nonatomic, weak) UIView *waterRefreshView;
// 上拉的view
@property (nonatomic, strong) UIView *loadMoreView;

// 水滴中央的图片样式
@property (nonatomic, strong) UIImageView *refleshView;
// 刷新提示字时 前方显示的 图片样式
@property (nonatomic, strong) UIImageView *refreshRemindPicView;

// refresh上的提示label
@property (nonatomic, strong) UILabel *refreshRemind;
// loadMore上的提示label
@property (nonatomic, strong) UILabel *loadMoreRemind;

// loadMore转圈时显示的文字,比如 "加载中..",没有设置则转动图样居中显示
@property (nonatomic, strong) NSString *loadMoreIndicatorWord;

@property (nonatomic, weak) id <WaterRefreshDelegate>   refreshDelegate;
@property (nonatomic, weak) id <WaterLoadMoreDelegate>  loadMoreDelegate;
@property (nonatomic, assign, readonly) BOOL isRefreshing;
@property (nonatomic, assign, readonly) BOOL isLoadingMore;

// initial method
- (id)initWithWithType:(WaterViewType)type;

// !你需要在使用它的ScrollView 或者 VC的dealloc中调用这个方法
- (void)deallocWithCloseConnect;
/*w
 start: 自动开始水滴下拉刷新自动开始,另一种是靠你手去拖动触发
 end  : 结束水滴下拉刷新并显示提示动画,请传入提示语,你可能会想提示:"刷新成功",
 可指定提示图片
 */
- (void)startRefreshWithExpansion;
- (void)startRefreshWithExpansionWithoutDelegate;
- (void)endRefreshWithRemindsWords:(NSString *)remind remindImage:(UIImage *)remindImage;

/*
 start: 自动开始上拉加载,另一种是靠手去上拉
 end  : 停止上拉加载,可给予提示
 */
- (void)startLoadingMoreExpansion;
- (void)startLoadingMoreExpansionWithOutDelegate;
- (void)endLoadingMoreWithRemind:(NSString *)remind;

// 禁掉loadMore的上拉加载功能,ban为YES时提示语默认为“没有更多内容”
- (void)banFunctionOfStartLoadMore:(BOOL)ban remind:(NSString *)remind;

- (void)setWaterRefreshColor:(UIColor*)color;
@end

@protocol WaterRefreshDelegate <NSObject>
// 水滴下拉刷新的代理方法
- (void)slimeRefreshStartRefresh:(WaterRefreshLoadMoreView*)refreshView;
- (void)slimeRefreshEndRefresh:(WaterRefreshLoadMoreView *)refreshView;
@end

@protocol WaterLoadMoreDelegate <NSObject>

@optional
// 加载更多的代理方法
- (void)loadMoreViewStartLoad:(WaterRefreshLoadMoreView*)refreshView;
- (void)loadMoreViewEndLoad:(WaterRefreshLoadMoreView *)refreshView;
@end

WaterRefreshLoadMoreView.h


//
//  WaterRefreshLoadMoreView.m
//  shiyanforwaterfresh
//
//  Created by 俊涵 on 13-9-19.
//  Copyright (c) 2013年 俊涵. All rights reserved.
//

#import "WaterRefreshLoadMoreView.h"
#import "SRSlimeView.h"
#import <QuartzCore/QuartzCore.h>

#define KEYPATH_CONTENTOFFSET       @"contentOffset"
#define KEYPATH_CONTENTSIZE         @"contentSize"

#define STRING_LOADMORE             @"加载更多"
#define STRING_NOMORE               @"没有更多内容"

#define HEIGHT_DEFAULT              40.0f
#define DURIATION_ANIMATE           0.2f
#define DURIATION_SHOWNOMORE        1.5f
#define TAG_LOADMORE_INDICATOR      200
#define kRefreshImageWidth          20.0f
#define kDistanceFromRemind         10.0f

static int scrollViewObservanceContext;
static int scrollViewContentSizeContext;

typedef enum {
    FooterViewStateNormal,
    FooterViewStateNormalPullling,
    FooterViewStateLoadingMore
}FooterViewState;

@interface WaterRefreshLoadMoreView()
{
    UIImageView     *_refleshView;
    SRSlimeView     *_slime;
}

@property (nonatomic, assign) FooterViewState footerState;

@property (nonatomic, strong) SRSlimeView *slime;
@property (nonatomic, strong) UIActivityIndicatorView *loadMoreActivityView;

@property (nonatomic, assign) BOOL closeLoadMore;
@property (nonatomic, assign) BOOL endAnimation;
@property (nonatomic, assign) BOOL endRefreshWithRemind;
@property (nonatomic, assign) BOOL broken;
@property (nonatomic, assign) BOOL slimeMissWhenGoingBack;
@property (nonatomic, assign) BOOL lastDragScroll;
@property (nonatomic, assign) BOOL isHasMoreContent;

@property (nonatomic, assign) CGFloat upInset;
@property (nonatomic, strong) NSString *refreshRemindWord;
@property (nonatomic, strong) NSString *loadMoreRemindWord;

@property (nonatomic, strong) UITapGestureRecognizer *gesture;

@end

@implementation WaterRefreshLoadMoreView {
    UIActivityIndicatorView *_activityIndicatorView;
    CGFloat     _oldLength;
    BOOL        _unmissSlime;
    CGFloat     _dragingHeight;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [self initWithHeight:HEIGHT_DEFAULT];
    return self;
}

- (id)initWithWithType:(WaterViewType)type
{
    self = [self initWithHeight:HEIGHT_DEFAULT];
    self.type = type;
    return self;
}

- (id)initWithHeight:(CGFloat)height
{
    CGRect frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, height);
    self = [super initWithFrame:frame];
    if (self) {
        // slime
        _slime = [[SRSlimeView alloc] initWithFrame:self.bounds];
        _slime.startPoint = CGPointMake(frame.size.width / 2, height / 2);
        [self addSubview:_slime];
        [_slime setPullApartTarget:self
                            action:@selector(pullApart:)];
        // 刷新图样
        _refleshView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"waterRefreshLoadMore_refresh"]];
        _refleshView.center = _slime.startPoint;
        _refleshView.bounds = CGRectMake(0.0f, 0.0f, kRefreshImageWidth, kRefreshImageWidth);
        [self addSubview:_refleshView];
        // indicator
        _activityIndicatorView = [[UIActivityIndicatorView alloc]
                                  initWithActivityIndicatorStyle:
                                  UIActivityIndicatorViewStyleGray];
        _activityIndicatorView.center = _slime.startPoint;
        [self addSubview:_activityIndicatorView];
        // refreshRemind
        self.refreshRemind = [[UILabel alloc] initWithFrame:_slime.frame];
        [self addSubview:self.refreshRemind];
        self.refreshRemind.backgroundColor = [UIColor clearColor];
        self.refreshRemind.textAlignment = NSTextAlignmentCenter;
        self.refreshRemind.textColor = [UIColor grayColor];
        self.refreshRemind.font = [UIFont systemFontOfSize:13.0f];
        self.refreshRemind.hidden = YES;
        // refreshRemindPicView
        self.refreshRemindPicView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, kRefreshImageWidth, kRefreshImageWidth)];
        [self addSubview:self.refreshRemindPicView];
        self.refreshRemindPicView.hidden = YES;
        // 设置拖拽临界点的高度
        _dragingHeight = height;
        self.slimeMissWhenGoingBack = NO;
        self.waterRefreshView = self;
    }
    return self;
}

- (void)setWaterRefreshColor:(UIColor*)color
{
    [_activityIndicatorView setColor:color];
    self.refreshRemind.textColor = color;
 //   _slime.bodyColor = color;
}

- (void)didMoveToSuperview
{
    [super didMoveToSuperview];
    if ([self.superview isKindOfClass:[UIScrollView class]]) {
        _scrollView = (id)[self superview];
        if (self.type == WaterRefreshTypeRefreshAndLoadMore || self.type == WaterRefreshTypeOnlyLoadMore) {
            [self addLoadMoreView];
        }
        self.isHasMoreContent = YES;
        // config frame
        CGRect rect = self.frame;
        rect.origin.y = rect.size.height ? -rect.size.height : -_dragingHeight;
        rect.size.width = _scrollView.frame.size.width;
        self.frame = rect;
        // inset
        UIEdgeInsets inset = self.scrollView.contentInset;
        inset.top = _upInset;
        self.scrollView.contentInset = inset;
        [self.scrollView addObserver:self forKeyPath:KEYPATH_CONTENTOFFSET options:0 context:&scrollViewObservanceContext];
        [self.scrollView addObserver:self forKeyPath:KEYPATH_CONTENTSIZE options:0 context:&scrollViewContentSizeContext];
        // configLoadMoreHide
        [self configLoadMoreHide];
    }else if (!self.superview) {
        self.scrollView = nil;
    }
}

- (void)addLoadMoreView
{
    // add loadmore
    CGFloat maxTop = self.scrollView.frame.size.height > self.scrollView.contentSize.height ? self.scrollView.frame.size.height : self.scrollView.contentSize.height;
    self.loadMoreView = [[UIView alloc] initWithFrame:CGRectMake(0, maxTop, [UIScreen mainScreen].bounds.size.width, HEIGHT_DEFAULT)];
    [self.scrollView addSubview:self.loadMoreView];
    self.loadMoreView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
    self.loadMoreActivityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
    self.loadMoreActivityView.tag = TAG_LOADMORE_INDICATOR;
    [self.loadMoreView addSubview:self.loadMoreActivityView];
    self.loadMoreActivityView.center = CGPointMake(self.loadMoreView.frame.size.width / 2, self.loadMoreView.frame.size.height / 2);
    [self showLoadMoreRemind:STRING_LOADMORE];
    // config loadMoreRemind
    self.loadMoreRemind = [[UILabel alloc] initWithFrame:self.loadMoreView.bounds];
    self.loadMoreRemind.backgroundColor = [UIColor clearColor];
    self.loadMoreRemind.font = [UIFont systemFontOfSize:12.0f];
    self.loadMoreRemind.textColor = [UIColor grayColor];
    self.loadMoreRemind.textAlignment = NSTextAlignmentCenter;
    [self.loadMoreView addSubview:self.loadMoreRemind];
    //self.loadMoreRemind.hidden = NO;
    [self showLoadMoreRemind:STRING_LOADMORE];
    // gesture
    self.gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(loadMoreActionByClick)];
    [self.loadMoreView addGestureRecognizer:self.gesture];
    self.footerState = FooterViewStateNormal;
    [self configLoadMoreHide];
}

- (void)loadMoreActionByClick
{
    [self scrollViewDataSourceDidStartLoadingMore:self.scrollView];
}

- (void)dealloc
{
    [self clearObservance];
}

- (void)deallocWithCloseConnect  // TODO :换成更好的办法
{
    [self clearObservance];
}

- (void)clearObservance
{
    [self.scrollView removeObserver:self forKeyPath:KEYPATH_CONTENTOFFSET context:&scrollViewObservanceContext];
    [self.scrollView removeObserver:self forKeyPath:KEYPATH_CONTENTSIZE context:&scrollViewContentSizeContext];
    self.scrollView = nil;
}

- (void)removeFromSuperview
{
    [NSObject cancelPreviousPerformRequestsWithTarget:self];
    [super removeFromSuperview];
}

#pragma mark - setters And getter

- (void)setScrollView:(UIScrollView *)scrollView
{
    if (_scrollView != scrollView) {
        _scrollView = scrollView;
        if (self.superview) {
            [self.loadMoreView removeFromSuperview];
            self.loadMoreView = nil;
            [self removeFromSuperview];
        }
        [self.scrollView addSubview:self];
    }
}

- (void)setType:(WaterViewType)type
{
    if (self.type == type) {
        return;
    }
    if (self.type != WaterRefreshTypeNone) {
        [self.scrollView removeObserver:self forKeyPath:KEYPATH_CONTENTOFFSET context:&scrollViewObservanceContext];
        [self.scrollView removeObserver:self forKeyPath:KEYPATH_CONTENTSIZE context:&scrollViewContentSizeContext];
    }
    _type = type;
    _isLoadingMore = NO;
    [self setFooterState:FooterViewStateNormal];
    self.closeLoadMore = NO;
    // 如果切换类型之前动画还未结束
    if (self.endAnimation == NO) {
        self.endAnimation = YES;
    }
    self.endRefreshWithRemind = NO;
    [self endRefreshWithRemindsWords:@"" remindImage:nil];
    [self endLoadingMoreWithRemind:@""];
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(collapse) object:nil];
    [self backStateOfScrollView];
    if (type == WaterRefreshTypeRefreshAndLoadMore || type == WaterRefreshTypeOnlyRefresh) {
        self.hidden = NO;
        self.loadMoreView.hidden = NO;
        UIScrollView *scrollView = self.scrollView;
        self.scrollView = nil; //clear
        self.scrollView = scrollView;
    } else if (type == WaterRefreshTypeOnlyLoadMore) {
        self.loadMoreView.hidden = NO;
        self.hidden = YES;
        UIScrollView *scrollView = self.scrollView;
        self.scrollView = nil; //clear
        self.scrollView = scrollView;
    } else if(type == WaterRefreshTypeNone) {
        self.hidden = YES;
        self.loadMoreView.hidden = YES;
    }
}

- (void)backStateOfScrollView
{
    UIEdgeInsets inset = self.scrollView.contentInset;
    inset.top = _upInset;
    inset.bottom = 0.0f;
    self.scrollView.contentInset = inset;
}

- (void)setFrame:(CGRect)frame
{
    [super setFrame:frame];
    if (_slime.state == SRSlimeStateNormal) {
        _slime.frame = CGRectMake(0.0f, 0.0f, frame.size.width, frame.size.height);
        _slime.startPoint = CGPointMake(frame.size.width / 2, _dragingHeight / 2);
    }
    _refleshView.center = _slime.startPoint;
    _activityIndicatorView.center = _slime.startPoint;
}

- (void)setUpInset:(CGFloat)upInset
{
    _upInset = upInset;
    UIEdgeInsets inset = _scrollView.contentInset;
    inset.top = _upInset;
    _scrollView.contentInset = inset;
}

- (void)setSlimeMissWhenGoingBack:(BOOL)slimeMissWhenGoingBack
{
    _slimeMissWhenGoingBack = slimeMissWhenGoingBack;
    if (!slimeMissWhenGoingBack) {
        _slime.alpha = 1;
    }else {
        CGPoint p = _scrollView.contentOffset;
        self.alpha = -(p.y + _upInset) / _dragingHeight;
    }
}

#pragma mark - Scroll handle

- (void)scrollViewDidScroll
{
    CGPoint offset = _scrollView.contentOffset;
    CGRect rect = self.frame;
    // 下拉刷新
    if (self.type == WaterRefreshTypeRefreshAndLoadMore || self.type == WaterRefreshTypeOnlyRefresh) {
        if (offset.y <= - _dragingHeight - _upInset) {
            // 处于拉伸变形的状态
            rect.origin.y = offset.y + _upInset;
            rect.size.height = -offset.y;
            rect.size.height = ceilf(rect.size.height);
            self.frame = rect; //special setFrame
            if (!self.isRefreshing) {
                [_slime setNeedsDisplay];
            }
            if (!_broken) {
                float l = -(offset.y + _dragingHeight + _upInset);
                if (l <= _oldLength) {
                    // 往回的时候
                    l = MIN(distansBetween(_slime.startPoint, _slime.toPoint), l);
                    CGPoint ssp = _slime.startPoint;
                    _slime.toPoint = CGPointMake(ssp.x, ssp.y + l);
                    CGFloat pf = (1.0f - l / _slime.viscous) * (1.0f - kStartTo) + kStartTo;
                    _refleshView.layer.transform = CATransform3DMakeScale(pf, pf, 1);
                }else if (self.scrollView.isDragging) {
                    // 手拽着往下拉伸的时候
                    CGPoint ssp = _slime.startPoint;
                    _slime.toPoint = CGPointMake(ssp.x, ssp.y + l);
                    CGFloat pf = (1.0f - l / _slime.viscous) * (1.0f - kStartTo) + kStartTo;
                    _refleshView.layer.transform = CATransform3DMakeScale(pf, pf, 1);
                }
                _oldLength = l;
            }
            if (self.alpha != 1.0f) self.alpha = 1.0f; //拉出来显示的时候可能 alpha不为1
        }else if (offset.y < -_upInset) {
            rect.origin.y = -_dragingHeight;
            rect.size.height = _dragingHeight;
            self.frame = rect;
            [_slime setNeedsDisplay];
            _slime.toPoint = _slime.startPoint;
            if (_slimeMissWhenGoingBack)
                self.alpha = -(offset.y + _upInset) / _dragingHeight;
        }
        if (self.isRefreshing && self.broken == NO) {
            // 配合适应inset避免 使用 tableview的话 section位置浮动错误
            UIEdgeInsets inset = _scrollView.contentInset;
            CGFloat offsetmath = MAX(_scrollView.contentOffset.y * -1, 0);
            offsetmath = MIN(offsetmath, HEIGHT_DEFAULT);
            inset.top = offsetmath;
            _scrollView.contentInset = inset;
        }
    }
    if ((self.type == WaterRefreshTypeRefreshAndLoadMore || self.type == WaterRefreshTypeOnlyLoadMore) && self.closeLoadMore == NO) {
        // 上拉
        if (self.footerState == FooterViewStateNormal) {
            if (self.scrollView.isDragging && [self offsetFromBottom:self.scrollView] > self.loadMoreView.frame.size.height + 5) {
                [self setFooterState:FooterViewStateNormalPullling];
                if (self.isHasMoreContent == NO) {
                } else {
                    [self scrollViewDataSourceDidStartLoadingMore:self.scrollView];
                }
            }
        } else if (self.footerState == FooterViewStateNormalPullling) {
            if (self.scrollView.isDragging && [self offsetFromBottom:self.scrollView] < self.frame.size.height + 5) {
                [self setFooterState:FooterViewStateNormal];
            }
        } else if (self.footerState == FooterViewStateLoadingMore) {
        }
    }
}

- (void)scrollViewDidEndDraging
{
    // 下拉刷新
    if (self.type == WaterRefreshTypeRefreshAndLoadMore || self.type == WaterRefreshTypeOnlyRefresh) {
        if (_broken) {
            self.broken = NO;
            if (self.isRefreshing) {
                [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
                [UIView animateWithDuration:DURIATION_ANIMATE animations:^{
                    UIEdgeInsets inset = _scrollView.contentInset;
                    inset.top = _upInset + _dragingHeight;
                    _scrollView.contentInset = inset;
                } completion:^(BOOL finished) {
                }];
            }
        }
    }
    // 上拉
    if ((self.type == WaterRefreshTypeRefreshAndLoadMore || self.type == WaterRefreshTypeOnlyLoadMore) && self.closeLoadMore == NO) {
        if (self.footerState == FooterViewStateNormalPullling) {
            if (self.isHasMoreContent == NO) {
            } else {
                [self scrollViewDataSourceDidStartLoadingMore:self.scrollView];
            }
        }
    }
}

#pragma mark - loadMore

- (void)relayoutLoadMoreViewAndInset
{
    if (self.closeLoadMore == YES) {
        return;
    }
    CGFloat max = self.scrollView.contentSize.height < self.scrollView.frame.size.height ? self.scrollView.frame.size.height - self.scrollView.contentSize.height : 0;
    UIEdgeInsets inset = self.scrollView.contentInset;
    inset.bottom = max + self.loadMoreView.frame.size.height;
    self.scrollView.contentInset = inset;
    CGFloat footerViewTop = MAX(self.scrollView.frame.size.height, self.scrollView.contentSize.height);
    self.loadMoreView.frame = CGRectMake(0, footerViewTop, self.loadMoreView.frame.size.width, self.loadMoreView.frame.size.height);
}

- (void)configLoadMoreHide
{
    if (self.type == WaterRefreshTypeRefreshAndLoadMore || self.type == WaterRefreshTypeOnlyLoadMore) {
        if (self.scrollView.contentSize.height < self.scrollView.frame.size.height) {
            self.loadMoreView.hidden = YES;
            self.closeLoadMore = YES;
            UIEdgeInsets inset = self.scrollView.contentInset;
            inset.bottom = 0.0f;
            self.scrollView.contentInset = inset;
        } else {
            self.loadMoreView.hidden = YES;
            self.closeLoadMore = YES;
            UIEdgeInsets inset = self.scrollView.contentInset;
            inset.bottom = self.loadMoreView.frame.size.height;
            self.scrollView.contentInset = inset;
            self.loadMoreView.hidden = NO;
            self.closeLoadMore = NO;
        }
    }
}

- (void)startLoadingMoreExpansion
{
    [self scrollViewDataSourceDidStartLoadingMore:self.scrollView];
}

- (void)startLoadingMoreExpansionWithOutDelegate
{
    [self scrollViewDataSourceDidStartLoadingMoreWithOutDelegate:self.scrollView];
}

- (void)endLoadingMoreWithRemind:(NSString *)remind
{
    if (self.type == WaterRefreshTypeNone || self.type == WaterRefreshTypeOnlyRefresh) {
        return;
    }
    if (_isLoadingMore) {
        self.loadMoreRemindWord = remind;
        [self safeStopLoadingMore:self.scrollView];
    }
}

- (void)safeStartLoadingMore:(UIScrollView *)scrollView
{
    if (!_isLoadingMore) {
        _isLoadingMore = YES;
    } else {
        return;
    }
    [self endRefreshWithRemindsWords:nil remindImage:nil];
    [self setFooterState:FooterViewStateLoadingMore];
    self.gesture.enabled = NO;
    self.loadMoreView.hidden = NO;
    [self showLoadMoreRemind:@""]; //清空
    [self.loadMoreActivityView startAnimating];
    // config 转动时提示
    [self configIndicatorPositionWithWord:self.loadMoreIndicatorWord];
    self.loadMoreRemind.alpha = 0.45f;
    // cofig animate with indicatorword
    NSTimeInterval animateDuration = 0.7f;
    [UIView animateWithDuration:animateDuration animations:^{
        self.loadMoreRemind.alpha = 1.0f;
    }];
    CAKeyframeAnimation *aniamtion = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
    aniamtion.values = [NSArray arrayWithObjects:
                        [NSValue valueWithCATransform3D:
                         CATransform3DRotate(CATransform3DMakeScale(0.01, 0.01, 0.1),
                                             -M_PI, 0, 0, 1)],
                        [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.6, 1.6, 1)],
                        [NSValue valueWithCATransform3D:CATransform3DIdentity], nil];
    aniamtion.keyTimes = [NSArray arrayWithObjects:
                          [NSNumber numberWithFloat:0],
                          [NSNumber numberWithFloat:0.6],
                          [NSNumber numberWithFloat:1], nil];
    aniamtion.timingFunctions = [NSArray arrayWithObjects:
                                 [CAMediaTimingFunction functionWithName:
                                  kCAMediaTimingFunctionEaseInEaseOut],
                                 [CAMediaTimingFunction functionWithName:
                                  kCAMediaTimingFunctionEaseInEaseOut],
                                 nil];
    aniamtion.duration = animateDuration;
    self.loadMoreActivityView.layer.transform = CATransform3DIdentity;
    [self.loadMoreActivityView.layer addAnimation:aniamtion forKey:@""];
    
}

- (void)safeStopLoadingMore:(UIScrollView *)scrollView
{
    if (!_isLoadingMore) {
        return;
    }
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView animateWithDuration:0.2f animations:^{
        self.loadMoreActivityView.layer.transform = CATransform3DRotate(CATransform3DMakeScale(0.01f, 0.01f, 0.1f), -M_PI, 0, 0, 1);
        self.loadMoreRemind.alpha = 0.2f;
    } completion:^(BOOL finished) {
        [self.loadMoreActivityView stopAnimating];
        self.loadMoreActivityView.layer.transform = CATransform3DRotate(CATransform3DMakeScale(1.0f, 1.0f, 1.0f), M_PI, 0, 0, 1);
        self.loadMoreRemind.alpha = 1.0f;
        [self relayoutLoadMoreViewAndInset];
        if (self.isHasMoreContent) {
            if (self.loadMoreRemindWord) {
                //错误提示语
                [self showLoadMoreRemind:self.loadMoreRemindWord];
                [self performSelector:@selector(backToLoadMoreRemind) withObject:nil afterDelay:1.0f];
            } else {
                [self showLoadMoreRemind:STRING_LOADMORE];
                _isLoadingMore = NO;
                [self setFooterState:FooterViewStateNormal];
                self.gesture.enabled = YES;
                if ([self.loadMoreDelegate respondsToSelector:@selector(loadMoreViewEndLoad:)]) {
                    [self.loadMoreDelegate loadMoreViewEndLoad:self];
                }
            }
        } else {
            if (self.loadMoreRemindWord) {
                if ([self.loadMoreRemindWord isEqualToString:@""]) {
                    self.loadMoreRemindWord = STRING_NOMORE;
                }
                [self showLoadMoreRemind:self.loadMoreRemindWord];
            } else {
                [self showNoContentRemind];
            }
            [self performSelector:@selector(setInsetBottomAnimateToZeroAndCallDelegate:) withObject:[NSNumber numberWithBool:YES] afterDelay:DURIATION_SHOWNOMORE];
        }
    }];
}

- (void)setInsetBottomAnimateToZeroAndCallDelegate:(NSNumber *)callDelegate
{
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView animateWithDuration:DURIATION_ANIMATE animations:^{
        [self setInsetBottomToZero];
    } completion:^(BOOL finished) {
        _isLoadingMore = NO;
        [self setFooterState:FooterViewStateNormal];
        if (self.isHasMoreContent) {
            self.gesture.enabled = YES;
        }
        if (callDelegate.boolValue) {
            if ([self.loadMoreDelegate respondsToSelector:@selector(loadMoreViewEndLoad:)]) {
                [self.loadMoreDelegate loadMoreViewEndLoad:self];
            }
        };
    }];
    [UIView commitAnimations];
}

- (void)setInsetBottomToZero
{
    UIEdgeInsets currentInsets = self.scrollView.contentInset;
    currentInsets.bottom = 0;
    self.scrollView.contentInset = currentInsets;
}

- (void)scrollViewDataSourceDidStartLoadingMore:(UIScrollView *)scrollView
{
    if (!_isLoadingMore) {
        [self safeStartLoadingMore:scrollView];
        if ([self.loadMoreDelegate respondsToSelector:@selector(loadMoreViewStartLoad:)]) {
            [self.loadMoreDelegate loadMoreViewStartLoad:self];
        }
    }
}

- (void)scrollViewDataSourceDidStartLoadingMoreWithOutDelegate:(UIScrollView *)scrollView
{
    [self safeStartLoadingMore:scrollView];
}

- (void)scrollViewDataSourceDidFinishLoadingMore:(UIScrollView *)scrollView
{
    [self safeStopLoadingMore:scrollView];
}

- (CGFloat)offsetFromBottom:(UIScrollView *)scrollView
{
    CGFloat change = scrollView.contentSize.height < scrollView.frame.size.height ? 0 :  scrollView.contentSize.height - scrollView.frame.size.height;
    return  scrollView.contentOffset.y - change;
}

- (void)showNoContentRemind
{
    self.loadMoreRemind.hidden = NO;
    [self showLoadMoreRemind:STRING_NOMORE];
}

- (void)showLoadMoreRemind:(NSString *)remindword
{
    self.loadMoreActivityView.hidden = YES;
    self.loadMoreRemind.hidden = NO;
    self.loadMoreRemind.text = remindword;
    self.loadMoreRemind.center = CGPointMake(self.loadMoreView.frame.size.width / 2, self.loadMoreView.frame.size.height / 2);
    self.loadMoreRemindWord = nil; //clear
}

- (void)backToLoadMoreRemind
{
    UILabel *label = self.loadMoreRemind;
    [UIView animateWithDuration:0.3f animations:^{
        label.alpha = 0.0f;
    } completion:^(BOOL finished) {
        [self showLoadMoreRemind:STRING_LOADMORE];
        [UIView animateWithDuration:0.3f animations:^{
            label.alpha = 1.0f;
            self.gesture.enabled = YES;
            _isLoadingMore = NO;
            [self setFooterState:FooterViewStateNormal];
            if ([self.loadMoreDelegate respondsToSelector:@selector(loadMoreViewEndLoad:)]) {
                [self.loadMoreDelegate loadMoreViewEndLoad:self];
            }
        }];
    }];
}

- (void)banFunctionOfStartLoadMore:(BOOL)ban remind:(NSString *)remind
{
    if (ban) {
        self.gesture.enabled = NO;
        self.isHasMoreContent = NO;
        if (remind) {
            self.loadMoreRemind.text = remind;
            [self endLoadingMoreWithRemind:remind];
        } else {
            self.loadMoreRemind.text = STRING_NOMORE;
            [self endLoadingMoreWithRemind:STRING_NOMORE];
        }
        [self performSelector:@selector(setInsetBottomAnimateToZeroAndCallDelegate:) withObject:[NSNumber numberWithBool:NO] afterDelay:DURIATION_SHOWNOMORE];
    } else {
        self.gesture.enabled = YES;
        self.isHasMoreContent = YES;
        if (!_isLoadingMore) {
            [self showLoadMoreRemind:STRING_LOADMORE];
        }
    }
}

- (void)configIndicatorPositionWithWord:(NSString *)word
{
    if (word && ![word isEqualToString:@""]) {
        // 如果有提供的文字就做左偏移
        self.loadMoreRemind.hidden = NO;
        self.loadMoreRemind.alpha = 1.0f;
        self.loadMoreRemind.text = word;
        CGSize size = [word sizeWithFont:self.loadMoreRemind.font constrainedToSize:CGSizeMake(self.loadMoreView.bounds.size.width, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
        CGRect rect = self.loadMoreRemind.frame;
        rect.size.width = size.width;
        rect.size.height = size.height;
        self.loadMoreRemind.frame = rect;
        self.loadMoreRemind.center = CGPointMake(self.loadMoreView.frame.size.width / 2, self.loadMoreView.frame.size.height / 2);
        self.loadMoreActivityView.center = CGPointMake(self.loadMoreRemind.frame.origin.x - kDistanceFromRemind, self.loadMoreActivityView.center.y);
        [self alignmentWithView:self.loadMoreActivityView lable:self.loadMoreRemind distance:kDistanceFromRemind totalWidth:self.scrollView.frame.size.width];
    } else {
        //还原
        self.loadMoreRemind.hidden = YES;
        UIActivityIndicatorView *indicator = (UIActivityIndicatorView *)[self.loadMoreView viewWithTag:TAG_LOADMORE_INDICATOR];
        indicator.center = CGPointMake(self.loadMoreView.frame.size.width / 2, self.loadMoreView.frame.size.height / 2);
        self.loadMoreRemind.center = indicator.center;
    }
}

- (void)alignmentWithView:(UIView *)view lable:(UILabel *)label distance:(CGFloat)distance totalWidth:(CGFloat)totalWidth
{
    CGFloat viewWidths = view.frame.size.width + distance + label.frame.size.width;
    CGFloat left = (totalWidth - viewWidths) / 2;
    view.center = CGPointMake(left + view.frame.size.width / 2 , view.center.y);
    label.center = CGPointMake(view.center.x + view.frame.size.width /2 + distance + label.frame.size.width / 2, label.center.y);
}

#pragma mark - refresh

- (void)setIsRefreshing:(BOOL)isRefreshing
{
    if (_isRefreshing == isRefreshing) {
        return;
    }
    _isRefreshing = isRefreshing;
    if (_isRefreshing) {
        [self endLoadingMoreWithRemind:nil];
        [_activityIndicatorView.layer removeAllAnimations];
        [_activityIndicatorView startAnimating];
        CAKeyframeAnimation *aniamtion = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
        aniamtion.values = [NSArray arrayWithObjects:
                            [NSValue valueWithCATransform3D:
                             CATransform3DRotate(CATransform3DMakeScale(0.01, 0.01, 0.1),
                                                 -M_PI, 0, 0, 1)],
                            [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.6, 1.6, 1)],
                            [NSValue valueWithCATransform3D:CATransform3DIdentity], nil];
        aniamtion.keyTimes = [NSArray arrayWithObjects:
                              [NSNumber numberWithFloat:0],
                              [NSNumber numberWithFloat:0.6],
                              [NSNumber numberWithFloat:1], nil];
        aniamtion.timingFunctions = [NSArray arrayWithObjects:
                                     [CAMediaTimingFunction functionWithName:
                                      kCAMediaTimingFunctionEaseInEaseOut],
                                     [CAMediaTimingFunction functionWithName:
                                      kCAMediaTimingFunctionEaseInEaseOut],
                                     nil];
        aniamtion.duration = 0.7;
        aniamtion.delegate = self;
        _activityIndicatorView.layer.transform = CATransform3DIdentity;
        [_activityIndicatorView.layer addAnimation:aniamtion
                                            forKey:@""];
        _refleshView.hidden = YES;
        if (!_unmissSlime){
            _slime.state = SRSlimeStateMiss;
        }else {
            _unmissSlime = NO;
        }
    }else {
        // 刷新结束
        [_activityIndicatorView stopAnimating];
        [_activityIndicatorView.layer removeAllAnimations];
        _refleshView.layer.transform = CATransform3DIdentity;
        [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
        [UIView animateWithDuration:0.35f animations:^{
            UIEdgeInsets inset = _scrollView.contentInset;
            inset.top = _upInset;
            _scrollView.contentInset = inset;
            if (_scrollView.contentOffset.y == -_upInset &&
                _slimeMissWhenGoingBack) {
                self.alpha = 0.0f;
            }
        } completion:^(BOOL finished) {
            _broken = NO;
            _slime.hidden = NO;
            _refleshView.hidden = NO;
            self.refreshRemind.text = @"";
            self.refreshRemindPicView.hidden = YES;
        }];
    }
}

- (void)startRefreshWithExpansion
{
    if (self.type == WaterRefreshTypeOnlyLoadMore || self.type == WaterRefreshTypeNone) {
        return;
    }
    if (self.isRefreshing) {
        return;
    }
    [UIView animateWithDuration:DURIATION_ANIMATE animations:^() {
        UIEdgeInsets inset = _scrollView.contentInset;
        inset.top = _upInset + _dragingHeight;
        _scrollView.contentInset = inset;
        [_scrollView setContentOffset:CGPointMake(_scrollView.contentOffset.x,
                                                  -_scrollView.contentInset.top)
                             animated:NO];
    }];
    [self startRefresh];
}

-(void)startRefreshWithExpansionWithoutDelegate{
    if (self.type == WaterRefreshTypeOnlyLoadMore || self.type == WaterRefreshTypeNone) {
        return;
    }
    if (self.isRefreshing) {
        return;
    }
    [UIView animateWithDuration:DURIATION_ANIMATE animations:^() {
        UIEdgeInsets inset = _scrollView.contentInset;
        inset.top = _upInset + _dragingHeight;
        _scrollView.contentInset = inset;
        [_scrollView setContentOffset:CGPointMake(_scrollView.contentOffset.x,
                                                  -_scrollView.contentInset.top)
                             animated:NO];
    } completion:^(BOOL finished) {
    }];
    self.isRefreshing = YES;
}

- (void)startRefresh
{
    self.isRefreshing = YES;
    if ([self.refreshDelegate respondsToSelector:@selector(slimeRefreshStartRefresh:)]) {
        [self.refreshDelegate slimeRefreshStartRefresh:self];
    }
}

- (void)pullApart:(WaterRefreshLoadMoreView*)refreshView
{
    self.broken = YES;
    _unmissSlime = YES;
    [self startRefresh];
}

- (void)endRefreshWithRemindsWords:(NSString *)remind remindImage:(UIImage *)remindImage
{
    if (self.type == WaterRefreshTypeOnlyLoadMore || self.type == WaterRefreshTypeNone ) {
        return;
    }
    if (self.isRefreshing && self.endRefreshWithRemind == NO) {
        self.refreshRemindWord = remind;
        self.refreshRemindPicView.image = remindImage;
        self.endRefreshWithRemind = YES;
        if (self.endAnimation == YES) {
            [self restore];
        }
    }
}

- (void)showRemindWordAndClear;
{
    if (!self.refreshRemindWord || [self.refreshRemindWord isEqualToString:@""]) {
        [self collapse];
        return;
    }
    self.refreshRemind.hidden = NO;
    self.refreshRemind.text = self.refreshRemindWord;
    self.refreshRemindWord = nil;
    [self performSelector:@selector(collapse) withObject:nil afterDelay:0.5f];
    
}

- (void)configRefreshPicViewPositionWithWord:(NSString *)word
{
    if (word && ![word isEqualToString:@""]) {
        // 如果有提供的文字就做左偏移
        //self.refreshRemindPicView.hidden = NO;
        self.refreshRemindPicView.alpha = 1.0f;
        CGSize size = [word sizeWithFont:self.refreshRemind.font constrainedToSize:CGSizeMake(self.bounds.size.width, MAXFLOAT) lineBreakMode:NSLineBreakByWordWrapping];
        CGRect rect = self.refreshRemind.frame;
        rect.size.width = size.width;
        rect.size.height = size.height;
        self.refreshRemind.frame = rect;
        self.refreshRemind.center = _slime.startPoint;
        self.refreshRemindPicView.center = CGPointMake(self.refreshRemind.frame.origin.x - kDistanceFromRemind, self.refreshRemind.center.y);
        [self alignmentWithView:self.refreshRemindPicView lable:self.refreshRemind distance:kDistanceFromRemind totalWidth:self.scrollView.frame.size.width];
    } else {
        //还原
        //self.refreshRemindPicView.hidden = NO;
        self.refreshRemindPicView.alpha = 1.0f;
        self.refreshRemindPicView.center = _slime.startPoint;
    }
}

- (void)restore
{
    _oldLength = 0.0f;
    _slime.toPoint = _slime.startPoint;
    [_activityIndicatorView.layer removeAllAnimations];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
    [UIView animateWithDuration:0.3f animations:^{
        _activityIndicatorView.layer.transform = CATransform3DRotate(CATransform3DMakeScale(0.01f, 0.01f, 0.1f), -M_PI, 0, 0, 1);
    } completion:^(BOOL finished)
     {
         [self relayoutLoadMoreViewAndInset];
         if (self.refreshRemindPicView.image) {
             self.refreshRemindPicView.hidden = NO;
             [self configRefreshPicViewPositionWithWord:self.refreshRemindWord];
         } else {
             [self alignmentWithView:nil lable:self.refreshRemind distance:0.0f totalWidth:self.scrollView.frame.size.width];
         }
         if (self.refreshRemindWord) {
             self.refreshRemind.hidden = NO;
             [self showRemindWordAndClear];
         } else {
             [self collapse];
         }
     }];
}

- (void)collapse
{
    if (_isRefreshing == NO) {
        return;
    }
    [self setIsRefreshing:NO];
    self.endRefreshWithRemind = NO;
    _slime.state = SRSlimeStateNormal;
    if ([self.refreshDelegate respondsToSelector:@selector(slimeRefreshEndRefresh:)]) {
        [self.refreshDelegate slimeRefreshEndRefresh:self];
    }
}

#pragma mark - Observer handle

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (context == &scrollViewObservanceContext) {
        // handle change
        if ([keyPath isEqualToString:KEYPATH_CONTENTOFFSET]) {
            [self scrollViewDidScroll];
            if (self.scrollView.dragging == YES && self.lastDragScroll == NO) {
                self.lastDragScroll = YES;
            } else if (self.scrollView.dragging == NO && self.lastDragScroll == YES) {
                self.lastDragScroll = NO;
                [self scrollViewDidEndDraging];
            }
        }
    }
    if (context == &scrollViewContentSizeContext) {
        if ([keyPath isEqualToString:KEYPATH_CONTENTSIZE]) {
            [self configLoadMoreHide];
            [self relayoutLoadMoreViewAndInset];
        }
    }
}

#pragma mark - Animation Delegate

- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag
{
    self.endAnimation = YES;
    if (self.endRefreshWithRemind == YES) {
        self.endRefreshWithRemind = NO;
        self.endAnimation = NO;
        [self restore];
    }
}

- (void)animationDidStart:(CAAnimation *)anim
{
    self.endAnimation = NO;
}

@end

WaterRefreshLoadMoreView.m


使用源码:

//
//  ViewController.m
//  Refresh
//
//  Created by YouXianMing on 14/11/21.
//  Copyright (c) 2014年 YouXianMing. All rights reserved.
//

#import "ViewController.h"
#import "WaterRefreshLoadMoreView.h"

@interface ViewController ()

@property (nonatomic, strong) UITableView               *tableView;
@property (nonatomic, strong) WaterRefreshLoadMoreView  *refreshLoadMoreView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, 320, 400)
                                                  style:UITableViewStylePlain];
    [self.view addSubview:self.tableView];
    
    _refreshLoadMoreView = [[WaterRefreshLoadMoreView alloc] initWithWithType:WaterRefreshTypeOnlyRefresh];
    _refreshLoadMoreView.scrollView = self.tableView;
}

- (void)dealloc {
    [_refreshLoadMoreView deallocWithCloseConnect];
}

@end

目录
相关文章
|
9月前
|
JavaScript
使用原生js实现上拉加载,下拉刷新
使用原生js实现上拉加载,下拉刷新
128 0
|
6天前
|
JavaScript
原生js如何实现上拉加载下拉刷新?
原生js如何实现上拉加载下拉刷新?
16 0
|
8月前
|
JSON 小程序 API
小程序下拉刷新的实现
小程序下拉刷新的实现
|
9月前
|
JavaScript Linux
【unapp】上拉加载,下拉刷新
【unapp】上拉加载,下拉刷新
69 0
|
10月前
|
小程序
小程序-uniApp:区域滚动、下拉刷新、上拉加载更多
小程序-uniApp:区域滚动、下拉刷新、上拉加载更多
505 0
|
11月前
SwipeRefreshLayout 下拉刷新控件(一)
SwipeRefreshLayout 下拉刷新控件(一)
|
11月前
SwipeRefreshLayout 下拉刷新控件(二)
SwipeRefreshLayout 下拉刷新控件(二)
|
iOS开发
iOS开发 - 让tableView不能下拉刷新,可以上拉加载
iOS开发 - 让tableView不能下拉刷新,可以上拉加载
274 0
|
JavaScript
原生js实现上滑加载,下拉刷新
这是手机端常见的一个功能,可能很多人都是用框架或者插件实现。 这里,我试着用原生js实现。 这样能更明白原理与底层实现
240 0
原生js实现上滑加载,下拉刷新
RecyclerView的下拉刷新和加载更多 动画
下拉刷新和加载更多 1、https://github.com/jianghejie/XRecyclerView 2、http://blog.csdn.net/jabony/article/details/44780187   动画 1、https://github.
1915 0