前言
一年前我在业余的时间做了一个课程表的界面,过程中基本上也很顺利的,近期由于一个校园项目的需要,所以就对其简单封装成了控件用在了项目中,但是在真正的项目中发现了很多当初没有考虑到的问题,所以在此将整个项目的历程记录一下,本篇主要以实例为主介绍课表的实现原理,基本不会涉及到代码,如果你有一定的Android基础,很容易根据原理实现一个自己的课表控件。
本篇博文主要讲解一下课表的实现原理,本项目已开源,地址如下:
思考问题
在讲解实现原理前先要思考以下几个问题:
- 课表的布局方式用什么?
- 课程实体的属性有哪些?
- 如何动态添加课程?
- 点击事件如何处理?
- 重叠课程与交叉课程如何处理以及如何处理此时的点击事件?
- 周次切换如何实现以及如何提高切换效率?
问题解答
课表的布局方式用什么?
- 定义七个线性布局,将这七个布局水平排列组成一个大的布局,这七个布局分别承载周一至周日的课程
- 七个布局均分,可以考虑使用weight
课程实体的属性有哪些?
- 课程名、教师、教室、时间,这几个属性可以根据需求增加或删除
- 上课的周次(整型集合)、星期(整型从0开始)、起始节次(整型从1开始)、步数(整型从1开始),这几个是必须的,课程在布局中的位置是用这几个属性计算出来的
- 所以,在动态添加布局前,必须先做一些预处理工作:将所有课程按照周一至周日的顺序拆分到七个集合中,并且在每个集合中的课程要求按照起始节次排好顺序
如何动态添加课程?
- 先定义好一个课程项的布局模板,然后使用LayoutInflate将布局转化为View,然后通过ID获取对应的View并修改其文本属性
- 注意:在正常情况下计算该View的margin值并不难,但是不得不考虑课程重叠以及交叉的情况
点击事件如何处理?
- 上一步动态的将布局转化为View后,可以对View设置点击事件监听器
- 当课程发生重叠或交叉时,点击之后需要将目标课程都找出来
重叠课程与交叉课程如何处理?
- 当检测到课程将要发生重叠或交叉时,可根据当前周以及所有将要发生重叠或交叉的课程的上课周次集合,排列出一个课程的展示优先级,将优先级低的课程屏蔽掉,将优先级高的课程展示出来
- 在处理交叉问题时要根据上一个课程的上课周次、将要交叉课程的上课周次、当前周来考虑
周次切换实现以及提高效率?
- 方法1:最简单的方法就是清除视图中所有布局,然后按照动态添加布局的方法再重新添加一遍,这种方法容易实现但是效率很低,经尝试发现在切换过程中可以发现明显的卡顿。
方法2:可以尝试复用布局,在切换布局的时候不清除布局,而是使用之前的布局,仅仅修改该布局的背景