This article will explain how to use and implement timeline effects with cumbersome custom views, and how to analyze and implement custom views. Knowledge needed: Paint, Canvas, custom View drawing process.

The source address

Welcome to leave a message.

First, there have been a lot of RecycleView timeline examples, why bother to use custom view to achieve the timeline?

First let’s look at the final desired effect:According to the above picture, the following points can be concluded:

  1. Each stage should display the time, stage name, status icon, dotted line in the middle;
  2. Text staggered display;
  3. Text in adjacent stages can intersect vertically;
  4. The number of timelines is uncertain, but should be spread across the screen and not swiped;

If only to achieve the effect of the two points, the use of RecycleView is undoubtedly the best choice, but to achieve the whole effect of the above is the best way to use custom view.

How to start?

I believe there are some people like me who are familiar with the use of custom drawing process, such as View, Canvas, path and paint. However, when it comes to writing a custom view, they don’t know how to start. My personal summary is: want too much, delay do not start, so have an idea must start to test! Don’t think that the first run is the final perfect effect you want to show, but rather to break the whole into small pieces that do not repeat, and then to draw the repeat blocks, and then to achieve the perfect step by step mentality.

Therefore, first of all, we need to divide the view we want to achieve into small drawable blocks without repetition. For the current timeline effect we want to achieve, the minimum drawable repeatable block is a block containing only one time node, as shown in the figure:It includes:

  • A dotted line vertically centered;
  • A status icon;
  • A block of text that displays the time;
  • A text block that displays the stage name;

Three, start drawing

With that analysis in mind, it’s time to start drawing.

1. Draw the middle line

Draw a dotted line first. If you don’t know how to draw a dotted line, you can draw a solid line first, and then you can find a way to draw a dotted line.

DrawLine (float startX, float startY, float stopX, float stopY, @nonnull Paint Paint) The start and end coordinates of the line and the paint object are the same. Since the line is vertically centered and crosses the entire control, the y coordinates of the two points are half the height of the control. The x coordinate of the start is 0 and the x coordinate of the end is the width of the control. The line can be drawn by knowing the width and height of the control. The width and height of the control can be obtained from the onMeasure method:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    mViewWidth = MeasureSpec.getSize(widthMeasureSpec) - dip2px(mContext, mSafeDistance * 2);
    mViewHeight = MeasureSpec.getSize(heightMeasureSpec);
}
Copy the code

Line drawing code (added in the onDraw method, as are the other drawing methods below) :

// Define the brush and set the related properties
Paint mLinePaint = new Paint();
mLinePaint.setColor(Color.parseColor("# 999999"));
mLinePaint.setStrokeWidth(1);
mLinePaint.setStyle(Paint.Style.STROKE);
/ / draw a dotted line
canvas.drawLine(0, mViewHeight / 2, mViewWidth, mViewHeight / 2, mLinePaint);
Copy the code

2. Drawing ICONS

Canvas drawing method: DrawBitmap (@nonnull Bitmap, float left, float top, @nullable Paint Paint); Starting coordinates and paint. A bitmap object can convert a resource file drawable into a Bitmap format. Coordinates are the center point of the control. Drawing code:

// icon x, y coordinates
Bitmap statusBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.ic_no_pass);
float bX = mViewWidth / 2;
// The vertical center point is at the top of the icon, so subtract half of the bitmap height
float bY = mViewHeight / 2 - statusBitmap.getHeight() / 2f;
Paint mBitmapPaint = new Paint();
mBitmapPaint.setFilterBitmap(true);
canvas.drawBitmap(statusBitmap, bX, bY, mBitmapPaint);
Copy the code

3. Draw the text

DrawText (@nonnull String text, float x, float y, @nonnull Paint Paint) is used to drawText on canvas. When the text is above the icon, the y-coordinate of the text should be used to subtract the distance between the text and the icon. The X-coordinate is the same as the x-coordinate of the image. When the text is below the icon, the y-coordinate of the text needs to use the icon’s y-coordinate plus the distance from the text to the icon. Code for drawing text:

// Define the brush
Paint mDatePaint = new Paint();
mDatePaint.setColor(Color.parseColor("# 666666"));
mDatePaint.setTextSize(dip2px(mContext, 12));
mDatePaint.setStyle(Paint.Style.FILL);
mDatePaint.setTextAlign(Paint.Align.CENTER);
mDatePaint.setAntiAlias(true);

Paint mNamePain = new Paint();
mNamePain.setColor(Color.parseColor("# 666666"));
mNamePain.setTextSize(dip2px(mContext, 13));
mNamePain.setStyle(Paint.Style.FILL);
mNamePain.setTextAlign(Paint.Align.CENTER);
mNamePain.setAntiAlias(true);

// Define coordinate variables
float dateX = bX + statusBitmap.getWidth() / 2f;
float dateY;
dateY = mViewHeight / 2 - dip2px(mContext, 19);

// Draw text on the icon
canvas.drawText("Effective time", dateX, dateY, mNamePain);
canvas.drawText("09.27-09.29", dateX, dateY - dateTextHeight mDatePaint);

// Draw text under the icon
dateY = mViewHeight / 2 + dip2px(mContext, 19);
canvas.drawText("09.27-09.29", dateX, dateY, mDatePaint);
canvas.drawText("Effective time", dateX, dateY + dateTextHeigh, mNamePain);
Copy the code

4. From the part to the whole

Now that you’ve done drawing at one point in time, think about how to draw at multiple points in time. When there is only one time point, the calculated coordinates are calculated based on the width and height of the control. When there are two time points, the control needs to be divided into two parts first, and then the corresponding coordinates are calculated in the evenly divided part to complete the drawing. When there are three time points, it is necessary to divide them into three parts, and then calculate corresponding coordinates in each part to complete the drawing. So no matter how many points in time you have, the way you draw it doesn’t change, what you need to change is the coordinates of the points that you’re drawing. In fact, we can already see that when multiple points need to loop, the code is as follows:

// The width of each part is the same as the width of the control with only one point in time
float itemW = mViewWidth / mDataList.size();
for (int i = 0; i < mDataList.size(); i++) {
    // Complete the calculation and drawing
}
Copy the code

5. Perfect

At this point, the whole analysis and drawing is almost finished.

SetPathEffect (new DashPathEffect(new float[]{10, 10}, 0));

SetLayerType (view.layer_type_software, null); setLayerType(view.layer_type_software, null);

The center point calculation of text drawing needs to be paid attention to for reference

Initialization of variables such as paint and bitmap is recommended in initializers rather than onDraw.

Four,

Be sure to see more about custom view and try more.