
文章插图
本篇文章会说下如何使用并且要用麻烦的自定义 view 去实现时间轴效果,以及如何分析、实现自定义 view 。需要具备的知识:Paint、Canvas、自定义 view 的绘制流程 。
欢迎留言交流 。
一、已经有很多 RecycleView 实现时间轴的例子,为何还要费劲的使用自定义 view 去实现时间轴?首先看下最终想要的效果:

文章插图
根据上图可以总结出以下几点:
- 每个阶段要显示时间、阶段名、状态图标、中间有虚线;
- 文字上下交错显示;
- 相邻阶段的文字在垂直方向上是可以相交的;
- 时间轴的个数不确定,但是要铺满屏幕并且不可滑动; 如果只实现上两点的效果,使用 RecycleView 无疑是最好的选择,但是要同时实现以上整个效果目前想到的最好的办法就是使用自定义 view 。
所以首先要把想实现的 view 拆分成一个个小的可绘制的并且没有重复的块,以目前想实现的时间轴效果来说,最小可绘制无重复块也就是只包括一个时间结点的块如图:

文章插图
它包括:
- 垂直居中的一条虚线;
- 一个表示状态的图标;
- 一个显示时间的文本块;
- 一个显示阶段名的文本块;
1. 画中间的线
首先画虚线,如果虚线不知道怎么画,可以先画一条实线,然后再去找画虚线的方法 。
使用 canvas 中画线的方法 drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint),根据参数得知需知道线的起点与终点坐标以及一个 paint 对象,因为是垂直居中且横穿整个控件的直线所以可以确定两个点的 y 坐标是一样的,也就是控件高的一半,起点的 x 坐标为0,终点的 x 坐标为控件的宽 。也就是知道控件的宽和高之后就可以绘制出这条线 。获取控件的宽高,可以在 onMeasure 方法中获取:
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mViewWidth = MeasureSpec.getSize(widthMeasureSpec) - dip2px(mContext, mSafeDistance * 2); mViewHeight = MeasureSpec.getSize(heightMeasureSpec);}画线的代码(在 onDraw 方法中添加,下面其它的绘制方法同样是在 onDraw 方法中添加):
// 定义画笔,并设置相关属性Paint mLinePaint = new Paint();mLinePaint.setColor(Color.parseColor("#999999"));mLinePaint.setStrokeWidth(1);mLinePaint.setStyle(Paint.Style.STROKE);// 画虚线canvas.drawLine(0, mViewHeight / 2, mViewWidth, mViewHeight / 2, mLinePaint);

文章插图
2. 画图标
canvas 画图标的方法:drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint),根据方法的参数去分析如何准备值,这里需要一个 bitmap 对象,起点坐标以及 paint 。bitmap 对象可以将资源文件 drawable 转为 bitmap 格式;坐标就是控件的中心点 。画图标的代码:
// 图标 x,y 坐标Bitmap statusBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_no_pass);float bX = mViewWidth / 2;// 垂直的中心点在图标的顶部,所以要减去 bitmap 高的一半float bY = mViewHeight / 2 - statusBitmap.getHeight() / 2f;Paint mBitmAppaint = new Paint();mBitmapPaint.setFilterBitmap(true);canvas.drawBitmap(statusBitmap, bX, bY, mBitmapPaint);3. 画文本
canvas 画文本的方法:drawText(@NonNull String text, float x, float y, @NonNull Paint paint),依然是根据方法得知需要知道绘制的内容,开始的坐标点以及 paint 。当文本在图标上方时,文本的 y 坐标需要使用图标的 y 坐标减去文本到图标的距离,x 坐标同图片的 x 坐标一样;当文本在图标下方时,文本的 y 坐标需要使用图标的 y 坐标加上文本到图标的距离 。画文本的代码:
推荐阅读
- android程序员hook技术之入门篇
- 在Android Studio中创建并引用aar
- iOS和Android OS的内存管理机制,这才是流畅的根本原因
- 防RSS采集,自定义WordPress RSS/Feed订阅发布推送
- 给Android开发者的几点启发性建议
- 找出Android卡顿的元凶——渲染性能优化
- 设置自定义404页面的重要性
- android6.0系统Healthd深入分析
- Google 是如何做 Code Review 的?| 原力计划
- win10下搭建flutter android应用开发环境
