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

  • 也就是说,这个view不仅要知道自身的颜色,还得知道上一个item是什么颜色的

  • 也就是说,这个view的绘制应该分成三个部分,分别是:上线、圆、下线

  • 这是一个普通的中间的item。然而对于第一个item和最后一个item来说,它们是分别没有上线和下线的

开始编码

====

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

第一版

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

  • 准备定义两个重要属性,它们将会参与计算位置和绘制内容

  • radius:用于确定圆的半径

  • offset:用于表示圆点到item顶部的距离

  • 并且在getItemOffsets中留出绘制整个时间线的空间,即item的左边距

  • 最重要的工作内容是我们计算并绘制了圆和线(具体的计算可以看代码)

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())// 省略构造假数据

rv_timeline1.addItemDecoration(FirstVerTimeline())

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

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

  • 定义paddingLeftpaddingRight属性,用来表示轴线的左右padding

  • 修改getItemOffsetsoutRect.left = paddingLeft + paddingRight + radius.toInt() * 2,留出偏移量的位置

  • 修改xPosition的初始值为radius + paddingLeft,改变轴线的x坐标

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

第二版

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

  • 数据类中肯定不可能耦合颜色这种UI实现,所以需要一个由状态获取颜色的办法

  • 由于画一个item还需要知道上一个item的颜色,干脆直接把整个数据源列表data传入ItemDecoration好了

  • 结合以上两点,我们可以定义一个函数类型的属性var color: (item: T) -> Int,实现这个属性就可以让使用者通过数据状态设置想要的颜色了

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

class SecondVerTimeline : RecyclerView.ItemDecoration() {

// 其他属性…

var data: List = 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…

}

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

  • 绘制上线前,需要通过data数据源获取到上一个item,并用color属性获得其状态对应的颜色

  • 绘制圆和下线前,同样需要改变到这一个item的颜色

  • parent.childCount获取到的子项数量指的是屏幕中可见的部分,必须要用parent.getChildAdapterPosition获取到该项在列表中的真正位置,才能确定下线要不要画。否则会出现【当前屏幕上可见的最后一项不是真正的最后一项,但它却没有下线,但向下滑动后它又有下线了】的尴尬场景

  • 注意到此时用于判断是否为最后一个item的方法,从count - 1变为了data.size - 1,用数据源的大小判断,比count更加准确(原因同上一条)

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

  • data设置给ItemDecoration

  • 通过color属性设置颜色策略

总结

Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!

上面分享的字节跳动公司2021年的面试真题解析大全,笔者还把一线互联网企业主流面试技术要点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节。

【Android高级架构视频学习资源】

Android部分精讲视频领取学习后更加是如虎添翼!进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!
ATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水,赶快领取吧!
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可获取!

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值