前言
最近app准备大改版,整体视觉全部换新。栏目管理功能也需要进行全新设计和改变,新版中加了不少动画效果。因为老版架构使用GridView进行栏目展示,但是GridView在栏目增加和删除时播放动画比较困难,而且老架构中栏目管理功能代码混乱,到底是重构还是重写?经过认真评估,最终决定重写该功能。
设计师要求的效果图如下:
分析
该模块主要有三个部分:
- 栏目添加、删除
- 栏目排序(拖拽)
- 动画
实现方案
在具体实现之前,有不少问题是需要确认或者是探索的。
问题1 GridView or RecyclerView ?
首先,对于栏目元素的展示,用GridView、RecyclerView都可以,但是GridView做添加删除动画比较困难,而RecyclerView本身就支持添加删除动画,因此这里选RecyclerView作为栏目元素的展示。
问题2 一个RecylerView or 三个RecylerView ?
一开始,我把三个模块(我的栏目、最近删除、更多栏目)都放在一个RecylerView上,后来发现把所有的逻辑都放在一个RecylerView和一个Adapter中是非常不明智的:1、会使代码更加臃肿;2、需要不断计算位置来判断某个栏目是属于我的栏目、最近删除还是更多栏目,逻辑十分复杂;3、代码扩展性不高,如果哪天产品说不想要最近删除这个功能了,又得大改。基于如上几个因素,选用三个RecylerView。
问题3 动画如何实现?
对于添加和删除动画,RecylcerView无缝支持,使用notifyItemInserted()和nofifyItemRemove()即可,对于漂移动画,就有点棘手了。一个比较简单的思路是:动画之前,先获取View截图,计算出起始坐标和终止坐标,然后添加到Activity根布局(contentView)中,做一个位移动画,然后再把该View截图从根布局中移除即可。
问题4 拖拽排序功能如何实现?
类似于ListView、GridView的ViewDragHelper,RecyclerView也有对应的拖拽帮助类ItemTouchHelper,只需要实现Callback,并重写一些简单的方法,便可以轻松实现拖拽排序功能。
想清楚了上面几个问题,完成整个功能已经不在话下了。
实现
具体实现效果如下(为了压缩gif,丢了不少帧,真机效果要流畅很多):
主要功能已经实现了,剩下的就是迁移业务逻辑了。
代码架构如下:
adapter作为数据适配器而存在,为了更好地灵活的区分不同点击事件的不同行为,抽象出clickhandler专门处理栏目点击事件,每个adapter都持有一个clickhandler对象。clickhandler代码如下:
1 | /** |
但是具体的点击事件单单由clickhandler来处理的话,需要传很多参数进去(如topRecyclerVIew,deleteRecyclerVIew,moreRecyclerView等),因此抽象出一个Controller,用来代理处理具体业务请求,Cotroller代码如下:
1 | /** |
显然,clickhandler也不需要做太多工作,比如MoreClickHandler代码如下:
1 | /** |
而真正具体的逻辑(添加、删除栏目、位移动画等)由谁来做比较合适呢?显然是ColumnTopEditFragment,因为ColumnTopEditFragment本身就持有topRecyclerVIew,deleteRecyclerVIew,moreRecyclerView这些对象,通过这些对象来实现具体逻辑是比较合适的。当然如果以后ColumnTopEditFragment代码越来越多,可以考虑把写另一个类实现ColumnController接口,并把需要的参数(topRecyclerVIew,deleteRecyclerVIew,moreRecyclerView)传进去,这样就可以把添加、删除、位移动画这部分逻辑挪出来。因此这里抽象出ColumnController是非常明智的,如果改天产品说更多栏目砍掉,现有代码框架也不需要做太多调整。