iOS 自定义刷新控件UIScrollView (Refresh)
2016-01-30 17:43
796 查看
开发的时候经常会用到下拉刷新这个控件,一直以来想自己写一个,但是时间问题,都是使用别人写好的,
今天查了资料,自己自定一个
1.主要原理:
a.创建UIScrollView的类目 提供 类似addHeaderRefresh等方法,这样tableview collectview等他们都是集成UIScrollView,所以可以直接条用类目提供的方法,(很多第三方基本都是这么干) 一般上拉 下拉都是捕获scrollview的偏移(contentoffset),但是在UIScrollview的类目里面如果捕获这个东西呢?我一开始是想通过类目里面自己实现scrollview的delegate,根据-
(void)scrollViewDidScroll:(UIScrollView
*)scrollView; 获取contentoffset,但是这样设计违背了设计理念:作为插件而言。就破坏了别人原本的逻辑。比如别人也需要监听这些行为。可能互相覆盖什么的。所以采用KVO的方式兼听属性contentoffset的变化
就很好的解决了这一点
b.再创建一个自定义的展示样式CustomRefreshView,这个view里面根据scrollview的偏移配置对应的UI展示 (捕获到“正在刷新”的状态的时候 利用外部传进来的刷新方法:SEL 和 执行方法的目标target 执行[self.actionTargetperformSelector:self.actionwithObject:nilafterDelay:0];
)
2.只是储备,类目的相关知识 对象关联等
直接上代码:(UIScrollView+Refresh).h
.m
-(void)dealloc
{
if (self.topShowView)//注册过刷新的必须要除移开监听
{
[self removeObserver:self forKeyPath:kObservePath context:kObserveContent];
}
}
@end
自定义展示的UI视图:
CustomRefreshView.h
.m
一个简单的下拉刷新就这么完成了,使用也很简单:
[self.tableViewaddHeaderRefreshWithTarget:selfaction:@selector(doLoadData)];
以下这两个方法都是直接对UI的操作 独立开来
[self.tableViewbeginHeaderRefresh];
[self.tableViewendHeaderRefresh];
看一下效果吧:
(Gifrocket 制作gif)
大体的样式完成了 接下来就可以根据自己的喜好自定义这个
CustomRefreshView,做一些酷炫的效果!
我的实现方式思路是参考这篇文章:http://blog.csdn.net/x6587305x/article/details/42640291
今天查了资料,自己自定一个
1.主要原理:
a.创建UIScrollView的类目 提供 类似addHeaderRefresh等方法,这样tableview collectview等他们都是集成UIScrollView,所以可以直接条用类目提供的方法,(很多第三方基本都是这么干) 一般上拉 下拉都是捕获scrollview的偏移(contentoffset),但是在UIScrollview的类目里面如果捕获这个东西呢?我一开始是想通过类目里面自己实现scrollview的delegate,根据-
(void)scrollViewDidScroll:(UIScrollView
*)scrollView; 获取contentoffset,但是这样设计违背了设计理念:作为插件而言。就破坏了别人原本的逻辑。比如别人也需要监听这些行为。可能互相覆盖什么的。所以采用KVO的方式兼听属性contentoffset的变化
就很好的解决了这一点
b.再创建一个自定义的展示样式CustomRefreshView,这个view里面根据scrollview的偏移配置对应的UI展示 (捕获到“正在刷新”的状态的时候 利用外部传进来的刷新方法:SEL 和 执行方法的目标target 执行[self.actionTargetperformSelector:self.actionwithObject:nilafterDelay:0];
)
2.只是储备,类目的相关知识 对象关联等
直接上代码:(UIScrollView+Refresh).h
// // UIScrollView+Refresh.h // SearchVCDemo // // Created by Programmer two on 16/1/30. // Copyright © 2016年 linpeng. All rights reserved. // #import <UIKit/UIKit.h> #import "CustomRefreshView.h" @interface UIScrollView (Refresh) @property (nonatomic,strong) CustomRefreshView *topShowView; -(void)addHeaderRefreshWithTarget:(id)target action:(SEL)action; -(void)beginHeaderRefresh; -(void)endHeaderRefresh; @end
.m
// // UIScrollView+Refresh.m // SearchVCDemo // // Created by Programmer two on 16/1/30. // Copyright © 2016年 linpeng. All rights reserved. // #import "UIScrollView+Refresh.h" #import <objc/runtime.h> #define kObservePath @"contentOffset" @implementation UIScrollView (Refresh) static char topShowViewKey; -(void)addHeaderRefreshWithTarget:(id)target action:(SEL)action { if (!self.topShowView) { self.topShowView = [[CustomRefreshView alloc] init]; } self.topShowView.frame = CGRectMake(0, -100, self.frame.size.width, 100); self.topShowView.parentView = self; self.topShowView.actionTarget = target; self.topShowView.action = action; [self addSubview:self.topShowView]; //兼听滚动便宜 [self addObserver:self forKeyPath:kObservePath options:NSKeyValueObservingOptionNew context:nil]; } -(void)beginHeaderRefresh { [self.topShowView beginHeaderRefresh]; } -(void)endHeaderRefresh { [self.topShowView endHeaderRefresh]; } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ([kObservePath isEqualToString:keyPath]) { NSValue *point = (NSValue *)[change objectForKey:@"new"]; CGPoint p = [point CGPointValue]; [self.topShowView adjustY:-p.y]; } } -(CustomRefreshView *)topShowView { return objc_getAssociatedObject(self, &topShowViewKey); } -(void)setTopShowView:(CustomRefreshView *)topShowView { objc_setAssociatedObject(self, &topShowViewKey, topShowView, OBJC_ASSOCIATION_RETAIN); }
-(void)dealloc
{
if (self.topShowView)//注册过刷新的必须要除移开监听
{
[self removeObserver:self forKeyPath:kObservePath context:kObserveContent];
}
}
@end
自定义展示的UI视图:
CustomRefreshView.h
// // CustomRefreshView.h // SearchVCDemo // // Created by Programmer two on 16/1/30. // Copyright © 2016年 linpeng. All rights reserved. // #import <UIKit/UIKit.h> typedef NS_ENUM(NSUInteger,RefreshStatus) { RefreshStatus_Normal = 1, RefreshStatus_BeginRefresh, RefreshStatus_Refreshing, }; @interface CustomRefreshView : UIView @property (nonatomic,strong)UILabel *updateLabel; @property (nonatomic,weak) id actionTarget; @property (nonatomic)SEL action; @property (nonatomic,strong) UIScrollView *parentView; @property (nonatomic) RefreshStatus refreshStatus; -(void)beginHeaderRefresh; -(void)endHeaderRefresh; -(void)adjustY:(CGFloat)y; @end
.m
// // CustomRefreshView.m // SearchVCDemo // // Created by Programmer two on 16/1/30. // Copyright © 2016年 linpeng. All rights reserved. // #import "CustomRefreshView.h" #define kMinOffSetY 100 @implementation CustomRefreshView -(instancetype)init { if (self = [super init]) { [self addSubview:self.updateLabel]; self.refreshStatus = RefreshStatus_Normal; } return self; } -(void)layoutSubviews { self.updateLabel.frame = CGRectMake(0, self.frame.size.height - 20, self.frame.size.width, 20); } -(void)beginHeaderRefresh { self.refreshStatus = RefreshStatus_Refreshing; } -(void)endHeaderRefresh { [self isAdjustToNormal:YES]; self.refreshStatus = RefreshStatus_Normal; } -(void)adjustY:(CGFloat)y { if (self.parentView.isDragging) { if (y>kMinOffSetY) { self.refreshStatus = RefreshStatus_BeginRefresh; } else { self.refreshStatus = RefreshStatus_Normal; } } else { if (y>kMinOffSetY) { self.refreshStatus = RefreshStatus_Refreshing; } } } -(void)isAdjustToNormal:(BOOL)normal { CGFloat y = 0; if (!normal) { y = 50; } __weak CustomRefreshView *weakSelf = self; [UIView animateWithDuration:0.5 animations:^{ weakSelf.parentView.contentInset = UIEdgeInsetsMake(y, 0, 0, 0); }]; } -(void)doNormalRefresh { self.updateLabel.text = @"下拉刷新...."; } -(void)doBeginRefresh { self.updateLabel.text = @"释放加载...."; } -(void)doRefreshing { self.updateLabel.text = @"正在努力加载..."; [self isAdjustToNormal:NO]; [self.actionTarget performSelector:self.action withObject:nil afterDelay:0]; } -(void)setRefreshStatus:(RefreshStatus)refreshStatus { if(_refreshStatus == refreshStatus) return; switch (refreshStatus) { case RefreshStatus_Normal: [self doNormalRefresh]; break; case RefreshStatus_BeginRefresh: { [self doBeginRefresh]; break; } case RefreshStatus_Refreshing: { [self doRefreshing]; break; } default: break; } _refreshStatus = refreshStatus; } -(UILabel *)updateLabel { if (_updateLabel == nil) { _updateLabel = [[UILabel alloc] init]; _updateLabel.textAlignment = NSTextAlignmentCenter; _updateLabel.font = [UIFont systemFontOfSize:13]; _updateLabel.textColor = [UIColor grayColor]; } return _updateLabel; } @end
一个简单的下拉刷新就这么完成了,使用也很简单:
[self.tableViewaddHeaderRefreshWithTarget:selfaction:@selector(doLoadData)];
-(void)doLoadData { __weak ViewController1 *weakSelf = self; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [weakSelf.tableView endHeaderRefresh]; }); }
以下这两个方法都是直接对UI的操作 独立开来
[self.tableViewbeginHeaderRefresh];
[self.tableViewendHeaderRefresh];
看一下效果吧:
(Gifrocket 制作gif)
大体的样式完成了 接下来就可以根据自己的喜好自定义这个
CustomRefreshView,做一些酷炫的效果!
我的实现方式思路是参考这篇文章:http://blog.csdn.net/x6587305x/article/details/42640291
相关文章推荐
- Codeforces 618B Guess the Permutation
- pat 1017queueing in bank (优先队列)
- [心得] 如何利用liquibase進行資料庫版本控制 - 實際練習
- String、StringBuffer、StringBuilder知识
- LinearLayout,RelativeLayout和UI优化的总结
- 工作队列(workqueue)
- smp boot up sequence
- Guideline--LM指南------------LeapMotion
- Java之GUI编程(一)
- UIImage渲染颜色
- [心得] 如何利用liquibase進行資料庫版本控制 - 基礎觀念
- priority_queue(优先队列)用法总结
- MySQL优化之慢日志分析(Anemometer+Pt-query-digest)
- Message Queue - MQ Intro
- jsp中request的常见使用方法
- UIGestureRecognizer手势
- PHP获取request payload(在header中)的方法
- LeetCode 303 Range Sum Query - Immutable(范围总和查询-永久不变)(*)
- [iOS]UICollectionView循环滚动功能的实现思路
- UIColor创建UIImage备忘