zoukankan      html  css  js  c++  java
  • 浅谈对MJRefresh(上)下拉刷新控件的理解

    MJRefresh GitHub地址:https://github.com/CoderMJLee/MJRefresh

    利用业余时间研究了一下iOS的开发,发现OC特定的语法方式吸引了我,而且iOS开发中有很多有趣的东西,正是如此,重新激起了我对开发学习的兴趣。自学过程中,知道了这个MJRefresh,MJ真乃大神也。

    废话不多说,MJRefresh集成了UIView,UICollectionView,UITableView的上下拉刷新功能,而且还有自定义文字,动画等功能。针对GitHub上的源代码研究了一翻,打算照抄一遍,理解里面的机制并且期待能从自己的实战中学到新的东西。相信敲完一遍之后对它的理解又是一个新的层次。

    MJRefresh的结构大致是这样子的:

    MJRefreshComponent自然是父类,它定义了基本的文字大小,颜色,刷新事件,block,以及开始刷新,结束刷新等基本操作和属性。

     1 @interface MJRefreshComponent : UIView
     2 {
     3     UIEdgeInsets _scrollViewOriginalInset;
     4     __weak UIScrollView *_scrollView;
     5 }
     6 
     7 #pragma mark - 文字处理
     8 /** 文字颜色 */
     9 @property (strong, nonatomic) UIColor *textColor;
    10 /** 字体大小 */
    11 @property (strong, nonatomic) UIFont *font;
    12 
    13 #pragma mark - 刷新处理
    14 /** 正在刷新的回调 */
    15 @property (copy, nonatomic) void (^refreshingBlock)();
    16 /** 设置回调对象和回调方法 */
    17 - (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action;
    18 @property (weak, nonatomic) id refreshingTarget;
    19 @property (assign, nonatomic) SEL refreshingAction;
    20 /** 进入刷新状态 */
    21 - (void)beginRefreshing;
    22 /** 结束刷新状态 */
    23 - (void)endRefreshing;
    24 /** 是否正在刷新 */
    25 - (BOOL)isRefreshing;
    26 @end

    我个人认为,最重要的两个类就是 MJRefreshHeader和MJRefreshFooter。因为刷新事件的精髓就在这两个类里面,Footer不多做介绍。我个人理解是,主要通过KVO监听 contentOffSet属性变化来判断当时是否是刷新、还是下拉、还是正在刷新或者改变刷新状态,核心代码当然我还是因为自身水平的原因没太看懂,相信敲完一遍之后会明白吧。核心代码如下:

    #pragma mark 根据contentOffset调整state
    - (void)adjustStateWithContentOffset
    {
        if (self.state != MJRefreshHeaderStateRefreshing) {
            // 在刷新过程中,跳转到下一个控制器时,contentInset可能会变
            _scrollViewOriginalInset = _scrollView.contentInset;
        }
        
        // 在刷新的 refreshing 状态,动态设置 content inset
        if (self.state == MJRefreshHeaderStateRefreshing ) {
            if(_scrollView.contentOffset.y >= -_scrollViewOriginalInset.top ) {
                _scrollView.mj_insetT = _scrollViewOriginalInset.top;
            } else {
                _scrollView.mj_insetT = MIN(_scrollViewOriginalInset.top + self.mj_h,
                                            _scrollViewOriginalInset.top - _scrollView.contentOffset.y);
            }
            return;
        }
        
        // 当前的contentOffset
        CGFloat offsetY = _scrollView.mj_offsetY;
        // 头部控件刚好出现的offsetY
        CGFloat happenOffsetY = - _scrollViewOriginalInset.top;
        
        // 如果是向上滚动到看不见头部控件,直接返回
        if (offsetY >= happenOffsetY) return;
        
        // 普通 和 即将刷新 的临界点
        CGFloat normal2pullingOffsetY = happenOffsetY - self.mj_h;
        if (_scrollView.isDragging) {
            self.pullingPercent = (happenOffsetY - offsetY) / self.mj_h;
            
            if (self.state == MJRefreshHeaderStateIdle && offsetY < normal2pullingOffsetY) {
                // 转为即将刷新状态
                self.state = MJRefreshHeaderStatePulling;
            } else if (self.state == MJRefreshHeaderStatePulling && offsetY >= normal2pullingOffsetY) {
                // 转为普通状态
                self.state = MJRefreshHeaderStateIdle;
            }
        } else if (self.state == MJRefreshHeaderStatePulling) {// 即将刷新 && 手松开
            self.pullingPercent = 1.0;
            // 开始刷新
            self.state = MJRefreshHeaderStateRefreshing;
        } else {
            self.pullingPercent = (happenOffsetY - offsetY) / self.mj_h;
        }
    }

    最后呢,通过UIScrollView+MJRefresh扩展来实现UIScrollView的控件下拉刷新集成。每多读一次代码就有一次新的收获。还等什么,赶紧去敲出来吧。

  • 相关阅读:
    【网易官方】极客战记(codecombat)攻略-游戏开发1-漫游者危险
    【网易官方】极客战记(codecombat)攻略-游戏开发1-军事训练
    【网易官方】极客战记(codecombat)攻略-游戏开发1-取舍
    【网易官方】极客战记(codecombat)攻略-游戏开发1-碾碎它
    【网易官方】极客战记(codecombat)攻略-游戏开发1-斩首老鼠
    课程报名 | 5G时代的视频云服务关键技术与实践
    干货 | 京东云账号安全管理最佳实践
    这大概是今年介绍云原生最清晰明了的文章!
    “大促”背后的技术 | 当我们说促销的时候,我们在谈什么?
    技术沙龙 | 从高并发架构到企业级区块链探索零售创新
  • 原文地址:https://www.cnblogs.com/panzi/p/5015472.html
Copyright © 2011-2022 走看看