上拉加载下拉刷新控件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 / ,
frame.size.height / );
_viscous = 45.0f; // 拉扯长度
_radius = 17.0f; // 拉扯物体半径
_bodyColor = [[UIColor grayColor] colorWithAlphaComponent:0.45f];
_skinColor = [[UIColor blackColor] colorWithAlphaComponent:0.12f];
_lineWith = 1.0;
_shadowBlur = ;
_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/ + (M_PI/) * percent;
CGPoint sp1 = pointLineToArc(_startPoint, _toPoint, angle1, startRadius),
sp2 = pointLineToArc(_startPoint, _toPoint, -angle1, startRadius),
ep1 = pointLineToArc(_toPoint, _startPoint, M_PI/, endRadius),
ep2 = pointLineToArc(_toPoint, _startPoint, -M_PI/, endRadius);
#define kMiddleP 0.6
CGPoint mp1 = CGPointMake(sp2.x*kMiddleP + ep1.x*(-kMiddleP), sp2.y*kMiddleP + ep1.y*(-kMiddleP)),
mp2 = CGPointMake(sp1.x*kMiddleP + ep2.x*(-kMiddleP), sp1.y*kMiddleP + ep2.y*(-kMiddleP)),
mm = CGPointMake((mp1.x + mp2.x)/, (mp1.y + mp2.y)/);
float p = distansBetween(mp1, mp2) / / endRadius * (0.9 + percent/);
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* - 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/
endAngle:angleS + M_PI*/
clockwise:YES];
[path addQuadCurveToPoint:sp1
controlPoint:mp2]; return path;
} - (void)drawRect:(CGRect)rect
{
switch (_state) {
case SRSlimeStateNormal:
{
float percent = - distansBetween(_startPoint , _toPoint) / _viscous;
if (percent == ) {
CGContextRef context = UIGraphicsGetCurrentContext();
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(_startPoint.x - _radius, _startPoint.y - _radius, *_radius, *_radius) cornerRadius:_radius];
[self setContext:context path:path];
CGContextDrawPath(context, kCGPathFillStroke);
}else {
CGFloat startRadius = _radius * (kStartTo + ( - kStartTo) * percent);
CGFloat endRadius = _radius * (kEndTo + ( - 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 <= ) {
_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 = - p;
float r = _radius * p; if (p > 0.01) {
CGFloat startRadius = r * (kStartTo + ( - kStartTo) * percent);
CGContextRef context = UIGraphicsGetCurrentContext(); CGFloat endRadius = r * (kEndTo + ( - kEndTo) * percent) * ( + percent / );
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(, , [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 / , height / );
[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(, , 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: context:&scrollViewObservanceContext];
[self.scrollView addObserver:self forKeyPath:KEYPATH_CONTENTSIZE options: 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(, 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 / , self.loadMoreView.frame.size.height / );
[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 / , _dragingHeight / );
}
_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 = ;
}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, );
}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, );
}
_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 * -, );
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 + ) {
[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 + ) {
[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 : ;
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(, 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, , , )],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.6, 1.6, )],
[NSValue valueWithCATransform3D:CATransform3DIdentity], nil];
aniamtion.keyTimes = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:],
[NSNumber numberWithFloat:0.6],
[NSNumber numberWithFloat:], 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, , , );
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, , , );
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 = ;
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 ? : 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 / , self.loadMoreView.frame.size.height / );
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 / , self.loadMoreView.frame.size.height / );
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 / , self.loadMoreView.frame.size.height / );
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) / ;
view.center = CGPointMake(left + view.frame.size.width / , view.center.y);
label.center = CGPointMake(view.center.x + view.frame.size.width / + distance + label.frame.size.width / , 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, , , )],
[NSValue valueWithCATransform3D:CATransform3DMakeScale(1.6, 1.6, )],
[NSValue valueWithCATransform3D:CATransform3DIdentity], nil];
aniamtion.keyTimes = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:],
[NSNumber numberWithFloat:0.6],
[NSNumber numberWithFloat:], 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, , , );
} 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(, , , )
style:UITableViewStylePlain];
[self.view addSubview:self.tableView]; _refreshLoadMoreView = [[WaterRefreshLoadMoreView alloc] initWithWithType:WaterRefreshTypeOnlyRefresh];
_refreshLoadMoreView.scrollView = self.tableView;
} - (void)dealloc {
[_refreshLoadMoreView deallocWithCloseConnect];
} @end

上拉加载下拉刷新控件WaterRefreshLoadMoreView的更多相关文章

  1. Vue mint ui用在消息页面上拉加载下拉刷新loadmore 标记

    之前总结过一个页面存在多个下拉加载的处理方式,今天再来说一下在消息页面的上拉加载和下拉刷新,基本上每个app都会有消息页面,会遇到这个需求 需求:每次加载十条数据,上拉加载下拉刷新,并且没有点击查看过 ...

  2. RecyclerView 上拉加载下拉刷新

    RecyclerView 上拉加载下拉刷新 <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/teach_s ...

  3. APICloud上啦加载下拉刷新模块

    apicloud有自带的上啦加载下拉刷新,当让也可以用第三方或者在模块库里面找一个使用 一.下拉刷新,一下代码写在 apiready = function (){} 里面 apiready = fun ...

  4. 微信小程序上拉加载下拉刷新

    微信小程序实现上拉加载下拉刷新 使用小程序默认提供方法. (1). 在xxx.json 中开启下拉刷新,需要设置backgroundColor,或者是backgroundTextStyle ,因为加载 ...

  5. mui scroll和上拉加载/下拉刷新

    mui中 scroll和上拉加载/下拉刷新同时存在会出现两个滚动条 把/*   */ /* //mui页面鼠标拖动代码: mui('.mui-scroll-wrapper').scroll({ dec ...

  6. Flutter上拉加载下拉刷新---flutter_easyrefresh

    前言 Flutter默认不支持上拉加载,下拉刷新也仅仅支持Material的一种样式.Android开发使用过SmartRefreshLayout的小伙伴都知道这是一个强大的刷新UI库,集成了很多出色 ...

  7. SwipeRefreshLayout实现上拉加载下拉刷新

    package com.example.swiperefreshlayoutdemo; import java.util.ArrayList;import java.util.HashMap; imp ...

  8. MJRefresh(上拉加载下拉刷新)

    整理自:https://github.com/CoderMJLee/MJRefresh#%E6%94%AF%E6%8C%81%E5%93%AA%E4%BA%9B%E6%8E%A7%E4%BB%B6%E ...

  9. 利用iscroll实现上拉加载下拉刷新

    1.首先引用isScroll插件 说明:页面加载时初始化isScroll,然后调用pullDownAction()和pullUpAction(),每次切换tab时,只需要对pullDownAction ...

随机推荐

  1. redis-手写redis切片和非切片连接池并注入springboot中

    spring-data整合了redispool, 并提供redisTemplate使用, 但有时需要用到shradedJedisPool, 就需要手动注入了 手写redispool并注入springb ...

  2. 7-nginx-keepalived配置主从双击热备

    nginx的高可用解决方案 keepalive 是 VRRP 协议的完美实现, 通过vip(虚拟ip)来实现主从双击热备, 自动切换的高可用方案, nginx的主从是通过keepalived实现的 通 ...

  3. 面试题42:计算逆波兰表达式(RPN)

    这是一个比较简单的题目,借助栈可以轻松实现逆波兰表达式. 题目描述: Evaluate the value of an arithmetic expression in Reverse Polish ...

  4. JavaScript中函数的变量提升问题

    函数的大体分三种,一种是函数的声明,一种是函数表达式(又称为函数的字面量) 1.函数的声明 => function myFn(){}; 2.函数的表达式 => var myFn = fun ...

  5. Hive学习之Locking

    众所周知,数据库必须要能够支持并发.无论在任何时候,允许同一时刻,多个用户能够同时读取或写入.没有必要给用户提供API显示的获取锁,所以所有的锁都是隐式获取的. 在Hive中有两种类型的锁: 共享锁S ...

  6. C# using用法

    一.using指令 使用using指令在文件顶部引入命名空间,如 using System; using System.IO; 二.using别名 用using为命名空间或类型定义别名,当引入的多个命 ...

  7. 【eclipse修改默认注释】

    一.背景简介 丰富的注释和良好的代码规范,对于代码的阅读性和可维护性起着至关重要的作用.几乎每个公司对这的要求还是比较严格的,往往会形成自己的一套编码规范.但是再实施过程中,如果全靠手动完成,不仅效率 ...

  8. 啰里吧嗦redis

    1.redis是什么 redis官网地址 Redis is an open source (BSD licensed), in-memory data structure store, used as ...

  9. 使用postman测试接口时需要先登录怎么办

    原文 1.在浏览器上先登录,登录成功后获取cookie: 2.接着打开postman:

  10. 实现一个符合 RESTful 架构的程序

    前言:在网上经常看到 RESTful,十分好奇,于是自己来试试. 代码地址:https://github.com/yuleGH/restdemo 首先,介绍一下 RESTful 架构:理解 RESTf ...