带你实现一个简单实用的时间线

闲来无事,给大家分享一个简单又实用的时间线,用自定义View来实现,效果图如下:

时间线效果图

相信有点自定义基础的哥们一看这个效果图就觉得很简单,还请各路大神不要吐槽哈。
首先来分析一下这个效果图,由三部分组成:
1.下面那条默认的线;
2.上面那条被选中的线;
3.以及线下面的文字。
绘制一条线,是自定义View中最基础的操作了,就是调用Canvas的drawLine方法,随便贴下代码:

/**Draw First Line*/
mPaint.setColor(mFirstColor);
mPaint.setStrokeWidth(mFirstLineHeight);
mPaint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawLine(
    mLineMargin, 
    mFirstLineHeight + (mSecondLineHeight - mFirstLineHeight) / 2.0f, 
    getWidth() - mLineMargin, mFirstLineHeight + (mSecondLineHeight - mFirstLineHeight) / 2.0f, 
                mPaint);

这里可能有些人不清楚怎么设置线段的两边为圆头,其实就是调用Paint的setStrokeWidth方法,参数是Paint.Cap里面的类型,有三种类型可选,分别是BUTT,ROUND,SQUARE,大家可以分别尝试一下效果。
下面在来绘制一下横线下面的文字。我们要把一天24小时,分成8个时间段,每个时间段3个小时,我们要把文字绘制在每个断点的中间,代码如下:

/**Draw Text*/
for (int i = 0; i <= LINE_TOTAL_COUNT ; i++) {
    mText = (LINE_NUM_FINISH - LINE_NUM_START) / LINE_TOTAL_COUNT * i + "";
    mTextBound = new Rect();
    mPaint.setTextSize(mTextSize);
    mPaint.setColor(mTextColor);
    mPaint.getTextBounds(mText,0,mText.length(), mTextBound);
    canvas.drawText(
        mText,
        mLinePerCountWidth * i + mLineMargin - (mTextBound.width() * 1.0f) / 2,
        mFirstLineHeight + mLineTextMargin, mPaint);
        }

这里有一个关键的地方就是怎么把文字绘制在断点的中间,就用到了Paint的getTextBounds这个方法,这个方法可以把文字的宽和高返回,这样我们在计算的时候,就可以根据文字的宽和高把它刚刚好放在线段的中间。
最后,就是来绘制一下上面那条选中的线,由于这里可能有多个线段是被选中的,比如0-3,5-8,9.7-12.8等等,因此这里采用了Map来保存被选中的时间段的开始和结束值。代码如下:

    /**Draw Second Line*/
if(mSelectedMap != null && mSelectedMap.size() > 0) {
    for (Map.Entry<Float, Float> entry : mSelectedMap.entrySet()) {
                                 mPaint.setStrokeWidth(mSecondLineHeight);
mPaint.setColor(mSecondColor);
float startNum = entry.getKey();
float finishNum = entry.getValue();
if(startNum >= 0 && finishNum <= 24 && finishNum > startNum) {
    canvas.drawLine(
        mLineMargin + mLinePerWidth * startNum,
        mSecondLineHeight - (mSecondLineHeight - mFirstLineHeight) / 2.0f,
        mLineWidth + mLineMargin - (LINE_NUM_FINISH - finishNum) * mLinePerWidth,
        mSecondLineHeight - (mSecondLineHeight - mFirstLineHeight) / 2.0f,
        mPaint);
     }
   }
}

这里除了绘制线段之外,还有一个知识点就是如何遍历Map可以既获得value又可以获得key,这里采用了Map.Entry来遍历,就可有巧妙的获得key和value。
好了,特别简单的一个控件,大家拿去用吧,最后附上下载地址:

DEMO下载地址

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值