目录
效果图
- 可控制是否绘制在中间
- 控制绘制的线条是否为虚线
- 控制第一条数据圆顶部线条和最后一条数据圆底部线条是否绘制
除了gif图片展示的属性,还可以控制圆的大小颜色、圆是否有上和左偏移、线条颜色等属性
除了通用的时间轴绘制,我们还可以通过改变绘制圆的样式,改为绘制相应的bitmap图像,来实现展示相关的流程
思路
关于ItemDecoration相关的内容已经写了不少,这个其实就是小菜一碟。我们需要做的工作有两点
- ItemDecoration在
getItemOffsets()
方法内做相应的偏移 - 在
onDraw()
方法内分别绘制圆、圆顶部线条、圆底部线条- 绘制线条,我们需要知道start和end的点坐标;
- 绘制圆,我们需要知道圆心和半径;
通过下图,你将能清楚地获取到这些绘制需要的一些信息
具体实现
有了以上内容,我们开始绘制
步骤一:ItemView顶部偏移
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State,
) {
if (parent.getChildAdapterPosition(view) != 0) {
//第一个不做顶部偏移
outRect.top = topItemSpace
}
outRect.left = leftItemSpace
}
步骤二:绘制圆和线条
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
//获取到的是当前屏幕可见的个数
val childCount = parent.childCount
for (i in 0 until childCount) {
val view = parent.getChildAt(i)
//获取真实的在整体数据中的位置
val index=parent.getChildAdapterPosition(view)
//ItemView左侧+偏移的矩形框(绿色框部分)
val spaceRectTop = if (index == 0) view.top else view.top - topItemSpace
val spaceRectBottom = view.bottom
val spaceRectLeft = view.left - leftItemSpace
val spaceRectRight = view.left
//ItemView左侧,不包含偏移的矩形框(红色框部分)
val dataRectLeft = view.left - leftItemSpace
val dataRectTop = view.top
val dataRectRight = view.left
val dataRectBottom = view.bottom
//圆心坐标
var centerX = if(isDrawAtMiddle) (dataRectLeft + dataRectRight)/ 2 else (dataRectLeft + dataRectRight)/ 2 + circleLeftPadding
val centerY =
if (isDrawAtMiddle) (dataRectTop + dataRectBottom) / 2 else dataRectTop + circleRadius + circleTopPadding
//绘制第一条线
if (index==0){
if (isDrawFirstItemTopLine){
c.drawLine(
centerX.toFloat(),
spaceRectTop.toFloat(),
centerX.toFloat(),
(centerY - circleRadius).toFloat(),
mLinePaint
)
}
}else{
c.drawLine(
centerX.toFloat(),
spaceRectTop.toFloat(),
centerX.toFloat(),
(centerY - circleRadius).toFloat(),
mLinePaint
)
}
//绘制圆(居中显示)
c.drawCircle(centerX.toFloat(), centerY.toFloat(), circleRadius.toFloat(), mCirclePaint)
//绘制第二条线,注意这里要用itemCount,因为上面的childCount是当前页面可见的个数
parent.adapter?.let {
if (index!=it.itemCount-1){
c.drawLine(
centerX.toFloat(),
(centerY + circleRadius).toFloat(),
centerX.toFloat(),
spaceRectBottom.toFloat(),
mLinePaint
)
}else{
if (isDrawLastItemBottomLine){
c.drawLine(
centerX.toFloat(),
(centerY + circleRadius).toFloat(),
centerX.toFloat(),
spaceRectBottom.toFloat(),
mLinePaint
)
}
}
}
}
}
注意:下标的获取
因为我们需要每个ItemView都绘制,所以需要使用循环。但因为val childCount = parent.childCount
获取到的是当前页面可见的个数,并不是实际的个数,所以我们在判断是否是首条或者最后一条数据时,那个index要通过val index=parent.getChildAdapterPosition(view)
的方式来获取到真实的下标位置。
流程类的绘制
和绘制通用的圆类似,不过是将Canvas.drawCircle()
改为Canvas.drawBitmap()
。至于不同的bitmap的加载,我们可以通过传入集合的数据类型来判断绘制哪种图片即可。
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
...
val srcRect = Rect(0, 0, progressBitmap.width, progressBitmap.height)
val dstRect = Rect(
centerX - circleRadius,
centerY - circleRadius,
centerX + circleRadius,
centerY + circleRadius
)
c.drawBitmap(errorBitmap, srcRect, dstRect, mCirclePaint)
...
}
总结
其实主要还是ItemDecoration相关的内容,在onDraw()
方法内绘制圆、绘制bitmap和绘制线条,根据上面的图,知道具体的坐标位置,绘制就很轻松了,也可以在此基础上继续扩展,使得我们的时间轴ItemDecoration更加的通用,方便运用到项目中。
如果本文对你有帮助,请别忘记三连,如果有不恰当的地方也请提出来,下篇文章见。
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容