上拉加载下拉刷新控件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.6CGPoint 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:_startPointradius:startRadiusstartAngle:angleS + angle1endAngle:angleS + M_PI*2 - angle1clockwise:YES];[path addQuadCurveToPoint:ep1controlPoint:mp1];angleS = atan2f(_startPoint.y - _toPoint.y,_startPoint.x - _toPoint.x);[path addArcWithCenter:_toPointradius:endRadiusstartAngle:angleS + M_PI/2endAngle:angleS + M_PI*3/2clockwise:YES];[path addQuadCurveToPoint:sp1controlPoint: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 pathUIBezierPath *path = [self bodyPath:startRadiusend:endRadiuspercent: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:_actionwithObject:self]; #pragma clang diagnostic pop[self performSelector:@selector(scaling)withObject:nilafterDelay:kAnimationIntervalinModes:[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:startRadiusend:endRadiuspercent: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:nilafterDelay:kAnimationIntervalinModes:[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:selfselector:@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; /*wstart: 自动开始水滴下拉刷新自动开始,另一种是靠你手去拖动触发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.0fstatic 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:selfaction:@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];// refreshRemindself.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;// refreshRemindPicViewself.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 frameCGRect rect = self.frame;rect.origin.y = rect.size.height ? -rect.size.height : -_dragingHeight;rect.size.width = _scrollView.frame.size.width;self.frame = rect;// insetUIEdgeInsets 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 loadmoreCGFloat 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 loadMoreRemindself.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];// gestureself.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; //clearself.scrollView = scrollView;} else if (type == WaterRefreshTypeOnlyLoadMore) {self.loadMoreView.hidden = NO;self.hidden = YES;UIScrollView *scrollView = self.scrollView;self.scrollView = nil; //clearself.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 setFrameif (!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 indicatorwordNSTimeInterval 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:aniamtionforKey:@""];_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 changeif ([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
转载于:https://www.cnblogs.com/YouXianMing/p/4113939.html
上拉加载下拉刷新控件WaterRefreshLoadMoreView相关推荐
- php微信小程序向下滑动,微信小程序功能实现:上滑加载下拉刷新
本篇文章给大家带来的内容是关于微信小程序功能实现:上滑加载下拉刷新,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 之前谈到文章列表的数据加载,是一次性全部加载,这样是不友好的.这章介 ...
- ionic上拉加载-下拉刷新
ionic上拉加载-下拉刷新 1.上拉加载 <ion-infinite-scroll on-infinite="loadOlderStories()" distance=&q ...
- Mint-ui中loadmore(上拉加载下拉刷新)组件在ios中滑动会触发点击事件的解决方法...
bug说明: Mint-ui中loadmore(上拉加载下拉刷新)组件 在 使用fastclick的情况下 ,在ios设备中滑动会触发点击事件: 解决方法: 我是按需引入,去项目中找到loadmore ...
- php mescroll,mescroll.js上拉加载下拉刷新组件使用详解
本文实例为大家分享了上拉加载下拉刷新组件mescroll.js的具体代码,供大家参考,具体内容如下 使用注意事项: 1.引入的时候出问题及时看官方给出的解决方案(基本上都必须看): 2.react中一 ...
- 教你如何使用SwipeRefreshLayout来构建一个上拉加载下拉刷新框架
前言: 基本上所以的移动端应用都有Listview(当然RecyclerView也一样),那必不可少的都会嵌入一个上拉加载下拉刷新的功能.这样能大大的减少用户的流量消耗,同样对于用户也有更好的用户体验 ...
- ios 上拉加载 下拉刷新
在一款 App应用中有的时候会用到上拉加载下拉刷新的功能,本人觉得SVPullToRefresh很好用(可以用在UIScrollView上,包括UITableview和UICollectionView ...
- 上拉加载下拉刷新了解下
2019独角兽企业重金招聘Python工程师标准>>> 老样子,我们先,哦不,今天我们直接上思路,没有效果图,真的没有 我们依旧从界面及逻辑两块进行分析 1.界面上,只分成简单的两块 ...
- 图片自动轮播+上拉加载下拉刷新+侧滑菜单+小圆点
//效果图如下 //添加权限 <uses-permission android:name="android.permission.INTERNET"></uses ...
- uniapp 自定义上拉加载下拉刷新组件
介绍 该组件是结合uview框架写的,主要结合了里面的u-loadmore组件,可配置下拉刷新加载圈的颜色及背景色,暂无数据时的图等,突出的特点就是通过设置组件的高度,适配刘海屏iPhone,且支持嵌 ...
- Android 智能上拉加载下拉刷新框架之SmartRefreshLayout
1.说明: SmartRefreshLayout的目标是打造一个强大,稳定,成熟的下拉刷新框架,并集成各种的炫酷.多样.实用.美观的Header和Footer.它不只是支持所有的View,还支持多层嵌 ...
最新文章
- 科研团队如何探索商业化落地?这家语音AI公司用十年科学试验打了样
- 一文读懂并发与并行,同步与异步阻塞
- Spark安装与学习
- 找出重复最多的字符php,javascript获取重复次数最多的字符_javascript技巧
- 并发编程-03线程安全性之原子性(Atomic包)及原理分析
- XCTF WEB weak_auth
- php opcache 详解
- oracle嵌套三层循环语句,在存储过程中执行3种oracle循环语句
- 苹果WWDC 2019最全剧透抢先看:iOS夜间模式要来了!
- ASP.NET Core管道深度剖析
- RigUp 数据库暴露7.6万份美国能源行业文件
- 100套精品PPT模板免费拿!以后再也不用怕老板叫你制作PPT了
- 腾讯云通信音视频通话最小化悬浮小窗
- 程序员如何缓解眼睛疲劳酸痛症状?
- 定位弹窗软件----找到真凶并做后续防御
- Python爬取王者荣耀官网图片
- 期权最新高频行情数据
- SSH Tunneling
- github上如何删除自己的仓库
- JavaScript内存相关初了解:堆栈、引擎、闭包隐患