项目里面也用到了自定义。不过是网上找了别人的插件 直接用。而且不是我负责的部分。所以没有好好看看。现在有时间 自己研究一下。然后在看看别人的源代码。首先先自己尝试着写个看看。
首先的整理开发思路:我们的目标是在当tableview 下拉 或者上拉 到一定程度。松开后触发事件。
先写下拉刷新
第一步 我们需要给tableview 的上下加上 2个用于显示加载更多 字样的 (或者 其他绚丽的自定义效果的加载效果)view。并且我们要监听到这2个view 滚到到视野中,触发加载更多的事件。显示的view 直接加载tableview上面就行了。top 写成 -50(这个view的高度)就行了。然后实现scrollview 的委托方法:
self.label= [[UILabel alloc] initWithFrame:CGRectMake(0, -50, 320, 50)];
[self.label setText:@"下拉刷新"];
[self.tableView addSubview: self.label];
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
int y = scrollView.contentOffset.y;
if(y<-50){
[self.label setText:@"松开刷新"];
}else{
[self.label setText:@"下拉刷新"];
}
// NSLog(@"%d",y);
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
int y = scrollView.contentOffset.y;
NSLog(@"xxxxx---%d",y);
}
这样就简单的效果就出来。下面处理一个逻辑scrollviewenddragging方法里面做逻辑 满足条件 取刷新界面。
发现一个问题。是用力往下滑。在没有达到刷新条件的时候松开。有惯性动画 会继续往下滑动。 会造成 scrollViewDidEndDragging 里面不满足刷新条件。 scrollViewDidScroll 里面的判断逻辑却能够满足条件。 看了下资料 应该在 scrollViewDidScroll里面加上判断 if([scrollViewisDragging]) 只有手指拖动的时候才改变这些文字。
第二步 需要做的是 当加载中的时候 将界面固定住。这时候就可以用到 UIEdgeInsets 了 当加载中的时候。给个 top 为 50 的UIEdgeInsets。这样 一个简单的 下拉刷新就完成了。当然这样使用很不好用。 需要写成独立的插件。下面尝试一下 修成可以即插即用的插件。
我的思路是 既然要通用。也要支持别人更换加载中的界面。 所以作为显示的view 需要实现我定义的一些协议:比如 刷新中 界面如何显示。 刷新结束 界面如何显示等等。
在这里需要说的是,发现别人是通过 addObserver 来处理的。这样明显更好。又不影响 之前的逻辑。如果像我那样 通过scrolldelegate 来实现。那么 作为插件而言。就破坏了别人原本的逻辑。比如别人也需要监听这些行为。可能互相覆盖什么的。
对于kvo的知识我以前都不知道。现在知道了还有个这么强大的功能。现在想想 利用这个功能应该可以实现很多以前效果。
同时发现如果写成uiscrollview的分类用起来也会方便很多。不过存在一个问题。就是分类是没法加属性的。查看别人的代码。发现了一个很有意思的东西:
objc_setAssociatedObject
导入写了一个简单的小架构。
UIScrollView+MyRefresh.h
//
// UIScrollView+MyRefresh.h
// test3
//
// Created by Aurora_sgbh on 15-1-16.
// Copyright (c) 2015年 Aurora_sgbh. All rights reserved.
//
#import
#import "DefaultTopLoadView.h"
@interface UIScrollView (MyRefresh)
@property(strong,nonatomic) DefaultTopLoadView *topShowView;
- (void)addTopTarget:(id)target andAction:(SEL)sel withView:(DefaultTopLoadView *)topShowView;
- (void) endRefresh;
@end
//
// UIScrollView+MyRefresh.m
// test3
//
// Created by Aurora_sgbh on 15-1-16.
// Copyright (c) 2015年 Aurora_sgbh. All rights reserved.
//
#import
#import "UIScrollView+MyRefresh.h"
#import "DefaultTopLoadView.h"
#import
@interface UIScrollView()
@end
@implementation UIScrollView (MyRefresh)
static char topShowViewChar;
//
- (void)addTopTarget:(id)target andAction:(SEL)sel withView:(DefaultTopLoadView *)topShowView{
if(self.topShowView){
[self.topShowView removeFromSuperview];
}
if(topShowView){
self.topShowView = topShowView;
}else{
self.topShowView = [[DefaultTopLoadView alloc]initWithFrame:CGRectMake(0, -50, 320, 50)];
}
DefaultTopLoadView* defaultTopLoadView= self.topShowView;
self.topShowView.action = sel;
self.topShowView.actionTar = target;
self.topShowView.topRefreshStatus = REFRESH_STATUS_NORMAL;
self.topShowView.parentScrollView =self;
[self addSubview:self.topShowView];
[self addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if([keyPath isEqualToString:@"contentOffset"]){
// NSLog(@"%@",change);
NSValue * point = (NSValue *)[change objectForKey:@"new"];
CGPoint p = [point CGPointValue];
// NSLog(@"%f---%f",p.x,p.y);
// [self.topShowView adjustStatus];
[self.topShowView adjustStatusByTop:p.y];
}
//NSLog(@"%@,%@,%@,%@",keyPath,object,change,context);
}
#pragma mark---自定义实现的get set 方法来实现分类增加属性功能
-(DefaultTopLoadView *)topShowView{
return objc_getAssociatedObject(self, &topShowViewChar);
}
-(void)setTopShowView:(DefaultTopLoadView *)topShowView{
objc_setAssociatedObject(self, &topShowViewChar,topShowView,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)endRefresh{
self.topShowView.topRefreshStatus = REFRESH_STATUS_NORMAL;
}
@end
//
// DefaultTopLoadView.h
// test3
//
// Created by Aurora_sgbh on 15-1-13.
// Copyright (c) 2015年 Aurora_sgbh. All rights reserved.
//
#import
@protocol TopViewDelegate
-(void) showBeforeRefresh;
@end
enum REFRESH_STATUS{
REFRESH_STATUS_NORMAL=1,
REFRESH_STATUS_BEFORE_REFRESH=2,
REFRESH_STATUS_REFRESHING=3,
// REFRESH_STATUS_NORMAL=1
};
@interface DefaultTopLoadView : UIView
@property(weak,nonatomic) id actionTar;
@property(assign,nonatomic) SEL action;
@property(assign,nonatomic) int topRefreshStatus;
@property(weak,nonatomic) UIScrollView *parentScrollView;
-(void)adjustStatusByTop:(float) y;
@end
//
// DefaultTopLoadView.m
// test3
//
// Created by Aurora_sgbh on 15-1-13.
// Copyright (c) 2015年 Aurora_sgbh. All rights reserved.
//
#import "DefaultTopLoadView.h"
@interface DefaultTopLoadView()
@property (strong,nonatomic) UILabel *showLabel;
@end
@implementation DefaultTopLoadView
-(instancetype)initWithFrame:(CGRect)frame{
self=[super initWithFrame:frame];
if(self){
self.showLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 40, 320, 10)];
[self.showLabel setText:@"test"];
[self addSubview:self.showLabel];
// [self addObserver:self forKeyPath:@"topRefreshStatus" options:NSKeyValueObservingOptionNew context:nil];
// [self addObserver:self forKeyPath:@"topRefreshStatus" options:NSKeyValueObservingOptionNew context:nil];
}
return self;
}
-(void)adjustStatusByTop:(float) y{
NSLog(@"%f----%f",y,self.frame.size.height);
if(self.parentScrollView.isDragging){
if(y<=self.frame.origin.y){
self.topRefreshStatus = REFRESH_STATUS_BEFORE_REFRESH;
}else{
self.topRefreshStatus = REFRESH_STATUS_NORMAL;
}
}else{
if(y<=self.frame.origin.y){
self.topRefreshStatus = REFRESH_STATUS_REFRESHING;
}
}
}
-(void)setTopRefreshStatus:(int)topRefreshStatus{
if(_topRefreshStatus == topRefreshStatus){
return;
}
switch (topRefreshStatus) {
case REFRESH_STATUS_NORMAL:{
[UIView animateWithDuration:0.25 animations:^{
self.parentScrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
self.parentScrollView.scrollEnabled = YES;
}];
[self showNormal];
break;
}
case REFRESH_STATUS_BEFORE_REFRESH:
[self showBeforeRefresh];
break;
case REFRESH_STATUS_REFRESHING:
{
[UIView animateWithDuration:0.25 animations:^{
self.parentScrollView.contentInset = UIEdgeInsetsMake(self.frame.size.height, 0, 0, 0);
self.parentScrollView.scrollEnabled = NO;
}];
[self showRefreshing];
[self.actionTar performSelector:self.action withObject:nil];
break;
}
default:
break;
}
_topRefreshStatus = topRefreshStatus;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
if([keyPath isEqualToString:@"topRefreshStatus"]){
// NSLog(@"%@",change);
NSNumber *statusNum = (NSNumber *)[change objectForKey:@"new"];
}
//NSLog(@"%@,%@,%@,%@",keyPath,object,change,context);
}
-(void) showBeforeRefresh{
[self.showLabel setText:@"松开刷新"];
}
-(void) showNormal{
[self.showLabel setText:@"下拉刷新"];
}
-(void) showRefreshing{
[self.showLabel setText:@"刷新中..."];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end
尝试这弄这个 也学到了一些东西;
首先就是 kvo 以前从来没有使用过。甚至不知道这个东西。 用起来才知道 真的很不错。 不过我的代码应该忘了取消监听了。 不改了。实际开发中一定要记得。
然后就是 objc_setAssociatedObject 很强大的功能。相信用的地方不会太多。不过有时候用它有奇效。
最后就是对之前了解的 UIEdgeInsetsMake 了解的更深刻了。
这个例子就到这里吧。感觉在写下去 也就是时间的问题了。