版权声明:
本公众号发布的所有文章,均属于原创,版权归本公众号所有。
Design Support Library (以下简称 DSL)是 Google 发布的一个全新的兼容函数库,它可以在 Android 2.1 (Api level 7)及以上的设备中,实现 Material Design 的效果,这个函数库同时也提供了一系列控件。
DSL 中提供的控件,有时间都会介绍到。其实掌握 DLS 里添加的控件,可能在实际工作中真的没什么用得着的地方,毕竟 App 长什么样子,UI、UE 来决定,代码层面的事情,才是我们需要负责的。而真的去研究 DSL 里的一些设计,你会发现 DSL 设计的很精妙,弄清楚它实现的原理,对你实现一些『奇葩』效果,会有很大帮助的。
今天介绍一个在 DSL 中承担一个万金油角色的控件 , CoordinatorLayout(以下简称CL) ,在 DSL 中,提供的很多效果,都是依赖 CoordinatorLayout 来实现的。而 CL 本身也非常的复杂,承载各种功能。本文在写着写着我发现并不能通过一篇文章完全写清楚 CL 。还好 CL 因为功能强大,所以可以通过一些方法的组合,实现部分功能,而 DSL 中,一般控件也只是用到了 CL 的部分功能而已。所以我决定进行拆分,一篇一篇的写。
在使用 DSL 之前,需要在 build.gradle 文件中,添加对其的依赖:
compile 'com.android.support:design:25.3.0'
CL 是一个直接继承自 ViewGroup 并实现 NestedScrollingParent 接口的控件,它主要的功能,就是协调其内部的各个子控件之间的状态关系。
简单来说,如果需要在布局中协调多个 View 进行互动,例如:移动、动画等等。在以前,是需要同时对这些 View 进行操作并响应各自的状态的,而有了 CL ,这些它都帮我们实现好了交互的接口,我们只需要去关心具体的细节。
在 DSL 中,很多地方都用到了 CL,举几个例子:
这些例子的效果,在 MD 的设计中,应该是随处可见的。
虽然这里讲的是 CL ,但是其实对于开发者而言,我们是不会和 CL 直接打交道的,而 CL 透出来的接口 Behavior 才是我们需要关心和实现的。
CL 和 Behavior 之间进行交互,将其内需要被协调的 View ,之间的变动,通过 Behavior 传递出来,开发者只需要针对 Behavior 中定义好的接口方法,进行对应的实现即可。
虽然 CL 可以实现的效果很多,但是我们先从最简单的来看,一个 View 依赖另外一个 View 的移动而移动。
类似上面的效果,当我们移动蓝色方块的时候,红色方块也跟着移动,这样红色方块可以一直保持和蓝色方块相同的距离,而如果接近边界,红色方块换位置,一致保持在蓝色方块的两边。
在以前,我们需要如何实现这样的一个效果?
首先需要监听蓝色方块的移动,然后在移动的时候,对外暴露一个接口,让红色方块也可以获取到蓝色方块移动的距离,然后跟随着进行移动。
而现在,只需要使用 CL ,实现一个我们需要的 Behavior 即可。
在讲具体实现之前,有一些 CL 相关的概念需要提前讲讲。
CL 和 Behavior 的通信模式有一点像设计模式里的观察者模式。对于 CL 内部的子 View 而言,都可以是被观察者,而 CL 观察这些被观察的 View 的行为,例如:移动、滚动等等,当观察到这些被观察的View的行为的时候,再通过 Behavior 通知给需要观察它状态的 View,被观察的View的变动情况。
说的有点乱,举个例子:就像警匪片里,卧底的身份一样,在观察到土匪有行动的时候,通知给警方,警方到底是收线抓人还是放长线钓大鱼,就是警方内部自己决定的了。
而在 Behavior 中,存在的角色就是 dependency 和 child 。如果 child 依赖 dependency 的行为来触发某些对应动作,那么他们之间就建立了依赖的关系。
首先,因为 Behavior 是一个泛型接口,并且被限定了只能是 View 类型的子类,这个泛型定义的 View,就是我们需要前面介绍的 child 角色。
而我们主要是对 Behavior 进行进行实现,主要需要用到它的两个方法。
和前面的描述一致,首先 Behavior 会通过 layoutDependsOn 方法,确定当前 child 是否和 dependency 有依赖关系,如果有,就把 dependency 的变动 ,传递给 child,否者就直接过滤掉。
layoutDependesOn 的完整签名如下:
onDependentViewChange 的完整签名如下:
既然已经了解了,在 CL 中,实现联动效果需要用到的 API 。那么接下来我们就实现一个 Behavior。
这里定义一个 TouchView 来实现触摸跟随移动的效果,代码非常的简单,这里就不贴了。再使用一个TetxView 来依赖 TouchView。然后我们就可以开始实现 Behavior 了。
和之前描述一样,首先通过 layoutDependsOn() 确定依赖关系,然后在 onDependentView() 方法内,根据依赖的变动,变动 child 即可。
在这里,首先确定 child 在 dependency 的方向,是左还是右,然后再计算出 child 最终的位置,进行变动。
实现好 Behavior 就可以在布局中,通过 app:layout_behavior
属性,为child 角色,定义它的 Behavior 。
最后达到的效果,就是本文前面给出的 gif 效果,这里就不重复贴图了。
虽然 CL 可以实现的功能非常的多,但是我们也需要由浅入深的去理解它,本文只是讲解了它最简单的使用方式,具体需要实现什么功能,是否用 CL 会比较合适,都需要看实际的效果来觉得。
最后,如果觉得不错,赞一个吧。