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

闲来无事,给大家分享一个简单又实用的时间线,用自定义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下载地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用Qt的QGraphicsView和QGraphicsScene来实现一个可以滑动的时间轴。具体步骤如下: 1. 创建一个QGraphicsView对象和一个QGraphicsScene对象。 2. 在QGraphicsScene中添加一个QGraphicsLineItem来表示时间轴的线。 3. 在QGraphicsScene中添加多个QGraphicsRectItem或者QGraphicsEllipseItem来表示时间轴上的事件。 4. 使用QGraphicsView来显示QGraphicsScene。 5. 实现鼠标拖动事件,在拖动的过程中改变QGraphicsScene的位置,从而实现时间轴的滑动。 下面是一个简单的示例代码,实现一个可以滑动的时间轴: ```cpp #include <QtWidgets> class TimeLineView : public QGraphicsView { public: TimeLineView(QWidget* parent = nullptr) : QGraphicsView(parent) { setDragMode(QGraphicsView::ScrollHandDrag); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setRenderHint(QPainter::Antialiasing); setViewportUpdateMode(QGraphicsView::FullViewportUpdate); setSceneRect(0, 0, 1000, 100); QGraphicsLineItem* line = new QGraphicsLineItem(0, 50, 1000, 50); line->setPen(QPen(Qt::black, 2)); scene()->addItem(line); for (int i = 0; i < 10; ++i) { QGraphicsRectItem* rect = new QGraphicsRectItem(i * 100, 25, 50, 50); rect->setBrush(QBrush(Qt::red)); scene()->addItem(rect); } } protected: void mousePressEvent(QMouseEvent* event) override { if (event->button() == Qt::LeftButton) { m_lastPos = event->pos(); } QGraphicsView::mousePressEvent(event); } void mouseMoveEvent(QMouseEvent* event) override { if (event->buttons() & Qt::LeftButton) { QPointF delta = mapToScene(event->pos()) - mapToScene(m_lastPos); m_lastPos = event->pos(); horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x()); } QGraphicsView::mouseMoveEvent(event); } private: QPoint m_lastPos; }; int main(int argc, char* argv[]) { QApplication app(argc, argv); TimeLineView view; view.show(); return app.exec(); } ``` 在这个示例代码中,我们创建了一个自定义的QGraphicsView类TimeLineView,其中我们重载了鼠标拖动事件,在拖动的过程中改变了水平滚动条的值,从而实现时间轴的滑动。在构造函数中,我们创建了一个QGraphicsScene对象,并在其中添加了一个QGraphicsLineItem和多个QGraphicsRectItem来表示时间轴上的线和事件。最后,我们将QGraphicsView设置为只能以手持模式拖动,并禁用了水平和垂直滚动条。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值