APP常见的滑动导航实现:TYPagerController源码分析(二)

写在前面

滑动导航的问题,主要是解决上方TabBar与下方ScrollView的联动问题。
在上一篇文章中,我们详细分析了ScrollView构成。
本篇我们就来看看作者是怎么处理联动问题的

一、TYTabPagerController,TYTabButtonPagerController总体介绍

TYTabPagerController在基类的基础上,主要做了两件事情:

  • 增加头部CollectionView
  • 增加滑动过程中的逻辑处理

而TYTabButtonPagerController在TYTabPagerController的基础上,也做了两件事情:

  • 增加了Label Cell至CollectionView(头部tabBar)
  • 实现了 TYTabPagerControllerDelegate协议的部分方法

二、TYTabPagerController详细分析

先看一个效果图:



重点看一下头部的tabBar,主要由两个部分组成:

  • 标签
  • UnderView

标签部分,我们可以用Label+ScrollView的方式实现,也可以直接使用CollectionView,推荐使用后者(为我们封装好了很多现成的功能,下文会提到)。
UnderView部分,根据Index和滑动比实时计算其frame就可以实现。
下面我们看看作者具体是怎么写得。

2.1 init

一如既往,只是简单的配置了下数据:

2.2 life Cycle

这部分,主要是各部分视图初始化,大体过程:

2.3 代理

2.3.1 TYTabPagerControllerDelegate

继承自基类中定义的TYPagerControllerDelegate,也是用来处理transition逻辑的:


2.3.2 setDelegate

在设置代理的时候,作者用一个struct记录了代理是否实现了相关方法,避免了后面冗余的检查代码,值得学习。

2.3.3 collectionViewDelegate

Paste_Image.png

2.4 滑动逻辑处理(重点)

在上一篇中,我们已经讨论过了滑动逻辑处理的总体计算流程:

TYTabPagerController主要实现了上图中提到的,子类、代理实现的处理index以及progress的方法

2.4.1 处理Index的方法

作用:在本方法中,调用在一次滑动过程中只需要处理一次的方法。
举例:通知delegate刚刚完成一次transition,或者调整collectionView的offset使选中Item居中显示



看看上面的流程图,回忆一下基类中的流程(只有当index发生改变的时候,该处理方法才会被调用)。
所以特别适合处理一次滑动只需要响应一次的事件,比如下图的选中Label自动居中的功能:

该功能的实现,是collectionView为我们封装好的:


注意上图我的注释,『如果可能的话』,什么情况下才会生效?
起始这个功能的实现,本质上就是对CollectionView Offset的修改,而Offset是有范围的,很明显不能为了居中显示指定的Item,将Offset超范围修改。
所以,在左侧和右侧的Item被选中的时候,CollectionView的offset是不会被修改的。


2.4.2 处理Progress的方法

作用:在此方法中调用需要实时处理的方法
举例:修改underLineView的Frame,修改Label的transform、color等一切需要跟Progress实时互动的事件

在该方法中,调用了delegate处理progress相关的方法;
还调用了另一个核心方法:setUnderLineFrame

setUnderLineFrame

作用:实时设定underLineViewFrame
实现:根据toIndex、FromIndex和滑动比实时计算UnderViewFrame
难点:不同风格对应不同的计算公式


上面这一坨代码,是不是看起来很晕?别急,其实拆开来看,并不难,我们下面一一进行分析:
先指明一下作者设定的一个的变量:


这个属性的作用呢,就是指定underLineView的首尾距离与Cell首尾的距离的,特此说明一下方便理解。

一般风格TYPagerBarStyleProgressView

我们从最简单也是最常用的部分开始介绍:



为了便于分析,我们先假设underLineView的width与cell的width一致。
先分析originX:

  • 初始值:fromCell.frame.origin.x
  • 目标值:toCell.frame.origin.x
  • 变化值:(toCell.frame.origin.x - fromCell.frame.origin.x)

将变化值与我们的progress挂钩,就可以得到动态变化的width了。

按照我们的分析来看一下源代码。

图中标号为1的部分,toCellFrame.origin.x + targetUnderLineViewEdgeToCell,其实就是我们上面提到的目标值。
图中标号为2的部分,就是我们的初始值。
两者相减 X progress 就是我们需要的与Progress挂钩的动态变化值。
再加上标号3,我们的初始值,就得到了frame.origin.x的计算式。

再看width部分,一样的分析方法:

  • 初始值: fromCell.frame.width
  • 目标值: toCell.frame.width
  • 变化值: (toCell.frame.width - fromCell.frame.width)
  • 计算表达式:fromeCell.frame.width + (toCell.frame.width - fromCell.frame.width) X progress

原作者的表达式化简一下,会得到一样的式子。

Bounce风格TYPagerBarStyleProgressBounceView

Bounce风格的话,比常见的要麻烦一些,不过列计算表达式的方式还是一样的:

  • 初始值
  • 目标值
  • 变化值

只要找出这三者,就可以列出符合要求的表达式。

这个动画过渡,是以progress=0.5为分界,分成上下两个部分,我们先来看上半部分的动画:

X坐标:

  • 初始值:fromCellFrame.origin.x + fromEdge
  • 目标值:同初始值
  • 变化值:0

从动画中,我们也可以看到,这个阶段的originX一致保持初始值的状态。
width:

  • 初始值: fromeCellFrame.width - 2*fromEdge
  • 目标值:初始值 + fromEdge + cellSpacing + toEdge + toCellFrame.width - 2 *toEdge
  • 变化值: 目标值 - 初始值 = fromEdge + cellSpacing + toEdge + toCellFrame.width - 2 *toEdge
  • 表达式: 初始值 + 变化值progress2(这里之所以x2,是因为progress的变化范围为[0,5],而我们需要的变化区间为[0,1])

我们来看一下作者的源码:

图标1处即为初始值,图标2处为变化值,最后变化值与2*progress相乘。

小结

分析方法就是这么简单,找出初始值、目标值、变化值,再确认我们的变化区间,就可以写出我们的目标表达式。
其它情况的分析方法也一样,这里就不再赘述了,有兴趣的朋友可以自己推导一下。


三、TYTabButtonPagerController分析

这个类,是作者为我们写好的一个滑动导航控制器,基本能满足我们的日常需求。
它主要是在TYTabPagerController的基础上,对一些细节进行了设置,总体没有什么难度,所以就不细讲了,感兴趣的同学可以自己看一下。
核心逻辑处理部分就一处:

与上一节的setUnderLineViewFrame同时进行,对Cell的颜色以及字体进行变换,代码很简单。

四、总结

至此,滑动导航控制器的第三方库分析已经完成了。
TYPagerController基本能满足我们的日常需求,当我们有更进一步的需求的时候,也可以再进行定制。
整体来说,代码的逻辑控制不错,要是变量名、方法名还有注释能更完善一些就更好了。
读起来还是有些不顺畅,不过也算是给自己提个醒:
『代码是写给人看的』

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容