刷新控件实现

作者: Hayder | 来源:发表于2016-12-10 12:36 被阅读99次

    刷新控件在项目中还是用的比较多的,可以依赖第三方框架做,但是如果自己的公司的刷新控件比较的特别,还是最好自己定制一个比较好,刷新分为上拉和下拉,实现起来都差不多,会了上拉,就只要改下刷新控件的3种状态变化的零界点和摆放位置,就可以实现上拉加载了。

    如图所示下拉刷新的实现框架

    下拉刷新.png

    1.刷新的3种状态

    先写一个emun,用来表示下刷新的3种状态

    typedef NS_ENUM(NSInteger, Status) {   
          StatusNormal, //正常状态
          StatusPulling, //释放刷新状态
          StatusRefreshing //正在刷新状态
    };
    

    2.初始化下拉刷新控件

    2.1初始化下拉刷新控件
    static CGFloat const headerHeight = 60;
    
    - (instancetype)initWithFrame:(CGRect)frame
    {
    
    if (self = [super initWithFrame:frame]) {
        
        self.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, headerHeight);
        
        self.backgroundColor = [UIColor whiteColor];
        
        //添加子控件
        [self addSubview:self.animView];
        [self addSubview:self.title];
        
        for (UIView *view in self.subviews) {
            
            view.translatesAutoresizingMaskIntoConstraints = NO;
        }
        
        //添加约束
        [self addConstraint:[NSLayoutConstraint constraintWithItem:self.animView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1 constant:-5]];
        [self addConstraint:[NSLayoutConstraint constraintWithItem:self.animView attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
        
        //text
        [self addConstraint:[NSLayoutConstraint constraintWithItem:self.title attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterX multiplier:1 constant:5]];
        [self addConstraint:[NSLayoutConstraint constraintWithItem:self.title attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
    
    }
    
         return self;
    }
    
    2.2 willMoveToSuperview找到父控件监听属性
    - (void)willMoveToSuperview:(UIView *)newSuperview{
    
        [super willMoveToSuperview:newSuperview];
    
        if ([newSuperview isKindOfClass:[UIScrollView class]]) {
        
            self.scrollView = (UIScrollView *)newSuperview;
        
        //监听tableView的contentSize contentOffset
            [self.scrollView addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];
            [self.scrollView addObserver:self forKeyPath:@"contentOffset" options:0 context:NULL];
        }
    }
    

    3 利用kvo监听Scrollview属性

    3.1在KVO中完成对属性的监听
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
    {
        //调整frame
        if ([keyPath isEqualToString:@"contentSize"]) {
        
            CGRect frame = self.frame;
            frame.origin.y = - headerHeight;
            self.frame = frame;
        //调整刷新控件的状态
    }else if ([keyPath isEqualToString:@"contentOffset"])
    {
        
            if (self.scrollView.isDragging) { //拖动
            
                if(self.scrollView.contentOffset.y > -headerHeight - 64)
                {
                    self.status = StatusNormal;
                
                }else if((self.scrollView.contentOffset.y <= -headerHeight - 64) && self.status == ZHPullDownHeaderViewStatusNormal) //当footerview完全显示并且,刷新控件的状态是normal时候才要改变状态
                {
                    self.status = StatusPulling;
                }
            }else
             {
                //停止刷新,pulling -> refershing
                if(self.status == StatusPulling)
                {
                    self.status = StatusRefreshing;
                }
            }
        }
    }
    
    3.2刷新控件的状态处理

    根据刷新控件的状态变化,对刷新控件上的控件进行设置
    - (void)setStatus:(Status)status
    {
    _status = status;

    switch (_status) {
            
        case StatusNormal:
            
            self.title.text = @"下拉刷新数据";
            self.animView.image = [UIImage imageNamed:@"normal"];
            
            break;
        case StatusPulling:
            
            self.title.text = @"释放刷新";
            self.animView.image = [UIImage imageNamed:@"pulling"];
            
            break;
        case StatusRefreshing:
        {
            self.title.text = @"正在刷新数据...";
            
            //动画view
            self.animView.animationImages = self.refershImages;
            self.animView.animationDuration = self.refershImages.count * 0.1;
            [self.animView startAnimating];
            
            UIEdgeInsets contentInset = self.scrollView.contentInset;
            contentInset.top = contentInset.top + headerHeight;
            self.scrollView.contentInset = contentInset;
            
            [UIView animateWithDuration:0.25 animations:^{
                
                self.scrollView.contentInset = contentInset;
                
            } completion:^(BOOL finished) {
                
                //让控制器加载数据
                if ((self.headerRefersh)) {
                    
                    self.headerRefersh();
                }
            }];
    
        }
            break;
            
        default:
            break;
        }
      }
    
    3.3 停止刷新
      - (void)endRefershing
      {
          if (self.status == StatusRefreshing) {
        
           [self.animView stopAnimating];
        
            UIEdgeInsets contentInset = self.scrollView.contentInset;
            contentInset.top = contentInset.top - headerHeight;
            self.scrollView.contentInset = contentInset;
        
            self.status = StatusNormal;
        }
      }
    

    4.delloc方法中移除监听

    使用NSNotification不移除监听者,会出现内存泄漏,使用kvo不移除,程序会崩溃!!!
    - (void)dealloc
    {
    //移除KVO的监听
    [self.scrollView removeObserver:self forKeyPath:@"contentSize"];
    [self.scrollView removeObserver:self forKeyPath:@"contentOffset"];
    }

    5.为方便使用为scrollview添加分类

    在UIScrollView+Refersh.h中
    #import <UIKit/UIKit.h>
    #import "HeaderView.h"

    @interface UIScrollView (Refersh)
    
    @property (nonatomic, strong) HeaderView *headerView;
    
    @end
    

    在UIScrollView+Refersh.m中

    static const char *headerViewKey = "headerViewKey";
    
    - (void)setHeaderView:(HeaderView *)headerView
    {
        objc_setAssociatedObject(self, headerViewKey, headerView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    
    - (ZHPullDownHeaderView *)headerView
    {
        ZHPullDownHeaderView *headerView = objc_getAssociatedObject(self, headerViewKey);
    
      //防止获取到为空
      if (!headerView) {
        
        headerView = [[HeaderView alloc] init];
        
        [self addSubview:headerView];
        
        self.headerView = headerView;
    }
    
        return headerView;
    }
    

    6.使用

    [self.tableView.headerView setHeaderRefersh:^{
       
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            
            [weakSwlf.tableView.headerView endRefershing];
            
            for (int i=0; i< 15; i++) {
                
                [weakSwlf.dataList insertObject:[NSString stringWithFormat:@"插入数据%d",i] atIndex:0];
            }
            
            [weakSwlf.tableView reloadData];
            
            
        });
    }];

    相关文章

      网友评论

        本文标题:刷新控件实现

        本文链接:https://www.haomeiwen.com/subject/mqrxmttx.html