Android进阶之路Android开发Android技术知识

又来新需求了,急,Android怎么实现时间线效果?

2020-04-16  本文已影响0人  Z_萧晓

背景

这天下班前,老板找到小庄:有个页面要优化,小需求,你跟进一下。
小庄:好的老板! 他看了看时间,忐忑地翻出原型,看到了这样一个页面:

思索片刻后,小庄熟练地打开了某搜索引擎,没有找到合适的轮子,小庄知道软件开发的第一步必须是先进行需求分析和设计,而不是撸起袖子一把梭。于是他决定先分析下功能并整理思路。

预警:本文非常啰嗦,而且没有干货(害怕.jpg)

分析

功能分析

页面的大致功能:

细节分析

某一个项的时间线view,其中有哪些细节呢?

开始编码

小庄现在已经有了基本的思路和知识储备,他打开IDE准备动手编码了。不过软件开发是迭代的过程,即使是这样的一个小需求,他也打算先从实现一个简单的版本开始。

第一版

第一个版本,小庄打算只实现画出圆和线的形状,没有状态也没有颜色,主要为了验证自己的想法是否可行,具体的实现需要做以下几个内容:

class FirstVerTimeline : RecyclerView.ItemDecoration() {

    private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
    var radius = 8f
    var offset = 15

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
        val count = parent.childCount
        for (i in 0 until count) {
            // 获取当前的itemView
            val itemView = parent.getChildAt(i)
            // 整个轴线的x坐标都是相同的
            val xPosition = radius

            // 画上线。第一个item不画
            if (i != 0) {
                c.drawLine(xPosition, itemView.top.toFloat(),
                            xPosition, itemView.top.toFloat() + offset, paint)
            }
            // 画下线。最后一个item不画
            if (i != count - 1) {
                c.drawLine(xPosition, itemView.top  + radius * 2 + offset, 
                            xPosition, itemView.bottom.toFloat(),paint)
            }
            // 画圆
            c.drawCircle(xPosition, itemView.top + offset + radius, radius, paint)
        }
    }

    override fun getItemOffsets(outRect: Rect, view: View, : RecyclerView, state: RecyclerView.State) {
        super.getItemOffsets(outRect, view, parent, state)
        // 设置item在左边的偏移量
        outRect.left = radius.toInt() * 2
    }
}

现在我们可以来定义一个虚拟的数据源Record,把这个ItemDecoration应用到一个RecyclerView上康康效果:

rv_timeline1.adapter = RecordAdapter(ArrayList<Record>())// 省略构造假数据
rv_timeline1.addItemDecoration(FirstVerTimeline())
复制代码

已经初具规模了!只是时间线和文字之间挤了一点,我们只需要加上一些合适的padding,换一下测试数据,看起来就会像真的一样了!

为了从图1到达图2,我们需要做:

到这里第一个版本就算完成啦,第二个版本会有什么新功能呢

第二版

小庄打算在第二版里实现状态的不同颜色。为了实现这个需求,他陷入了深深的沉思:

函数类型是kotlin(或者说函数式编程)的特性之一。如果是Java的话可以考虑用模板模式实现,即定义一个抽象方法让子类去重写

class SecondVerTimeline<T> : RecyclerView.ItemDecoration() {
    // 其他属性...
    var data: List<T> = ArrayList()  //-->这里有更新,定义了数据源

    var color: (item: T) -> Int = { _ -> Color.GRAY }  //-->这里有更新,通过这个属性设置颜色选择策略

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
        val count = parent.childCount
        for (i in 0 until count) {
            // ...
            val adapterPosition = parent.getChildAdapterPosition(itemView)  //-->这里有更新,获取当前项的真正位置
            val item = data[adapterPosition]  //-->这里有更新,获取当前项的数据源

            // 画上线。第一个item不画
            if (adapterPosition != 0) {
                paint.color = color(data[adapterPosition - 1])  //-->这里有更新,设置上线的颜色
                c.drawLine(...)
            }

            paint.color = color(item)  //-->这里有更新,设置圆和下线的颜色
            // 画下线。最后一个item不画
            if (adapterPosition != data.size - 1) {//-->这里有更新,改用数据源的大小判断是否为最后一个item
                c.drawLine(...)
            }
            // 画圆...
        }
    }
    // getItemOffsets...
}

代码中可能需要注意的点:

使用时也需要有一些变化:

val secondVerTimeline = SecondVerTimeline<Record>()
secondVerTimeline.data = records
secondVerTimeline.color = { item ->
    when (item.status) {
        1 -> color1
        2 -> color2
        ...
    }
}
rv_timeline2.addItemDecoration(secondVerTimeline)

然后就可以运行看一下效果了:

哇哦,鹅妹子嘤,这样就已经实现根据状态转变颜色的功能了!第二版的功能也圆满实现!

后话

后来小庄又根据UI一顿修修改改,很快就完成了这个需求~但是小庄是一个有追求的程序员,他开始思考起了这个代码的扩展性和通用性如何。不想不要紧,一想发现根本没有鸭!如果产品想要把圆点变成图片怎么办?或者产品想要更随风飞翔自由是方向呢?

于是他想找个时间完善改进一下这个ItemDecoration,最好能应对产品的所有需求!具体升级内容请看下集~

然而没有什么设计能做到一劳永逸,软件工作中唯一不变的就是变化,同时我们也不应该为了应对所谓的“未来可能发生的改动”而过度设计

最后对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!

这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司19年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。

相信它会给大家带来很多收获:

上述【高清技术脑图】以及【配套的架构技术PDF】可以 关注我 【主页简介】 或者【简信】免费获取

Android学习PDF+架构视频+面试文档+源码笔记

当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。

上一篇 下一篇

猜你喜欢

热点阅读