Android自定義控制元件之《折線圖的繪製》
金融軟體裡的行情分時圖,這是我們最常見的折線圖,當然了,折線圖的用途並不僅僅侷限於此,像一般在一定區間內,為了更好的能顯示出幅度的變化,那麼用折線圖來展示無疑是最符合效果的,當然了,網上也有很多的第三方開源,這篇文章呢,對開源的不做過多描述,想要了解請關注後續文章,好了,廢話不多說,讓我們從0來一步步繪製折線圖吧。
先來看一下我們最終要實現的效果:
很簡單的一個空氣質量折線圖,俗話說,磨刀不誤砍柴功,我們可以簡單的分析一下,這個折線圖主要包含了那幾塊,上面的標題可以做為一塊,xy座標軸是一塊,折線是一塊,簡單的分為三塊之後,程式碼我們就可以一塊一塊的去寫。
定義一個類繼承於View,實現其構造方法,先初始化我們需要的東西,背景設定偏黑色,初始化畫筆。
private void initView()
{
setBackgroundColor(Color.parseColor("#222222"));
mPaint = new Paint();
}
在onDraw()方法裡繪製標題:
/**
* 繪製標題
*/
private void canvasTitle(Canvas
canvas) {
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(50);
mPaint.setTypeface(blodFont);
canvas.drawText("
}
setTypeface()是用來設定字型,這裡我設定的是,宋體加粗
Typeface blodFont = Typeface.create("宋體", Typeface.BOLD);
在onDraw()方法裡繪製XY軸:
為了使整體看起來稍稍美觀,我們繪製的時候,儘量與上下左右保持一定的距離,這裡我設定的是距離底部為this.getBottom()-100,距離左邊為100,程式碼如下:
int marginBottom = this.getBottom()
- 100;
int marginLeft = 100
初始化XY軸:
//初始化X軸mPaint.setColor(Color.WHITE);
canvas.drawLine(marginLeft, marginLeft, marginLeft, marginBottom, mPaint);
//初始化Y軸mPaint.setStrokeWidth(6);
canvas.drawLine(marginLeft, marginBottom,
this.getRight() - 20, marginBottom, mPaint);
XY軸繪製好之後,緊接著我們繪製時間軸,時間軸,這裡我分成了5份,每份為5個小時,最後一份為4個小時,一份的寬度計算方式為:螢幕的寬度-距離右邊的寬度-距離左邊的寬度/5,程式碼如下:
int xWidth = (this.getRight() - 20 - marginLeft) / 5;
起始位置呢,就是距離左邊的距離:
int xLine = marginLeft;//起始位置
每一個時間點,都是逐個增加一份的寬度,這裡我們new一個Integer陣列來儲存:
Integer[] xPoint = new Integer[5];
for (int a = 0; a
< 5; a++)
{
xLine += xWidth;
xPoint[a] = xLine;
}
xPoint就是各個時間點的X軸座標,顯然Y軸是不變的,那麼我們就可以如下繪製;
for (int i
= 0; i
< xPoint.length; i++)
{
mPaint.setColor(Color.parseColor("#FF00FF"));
mPaint.setTextSize(40);
mPaint.setTypeface(font);
mPaint.setTextAlign(Paint.Align.RIGHT);
if (i == 0) {
canvas.drawText("0", marginLeft,
marginBottom + 50, mPaint);
canvas.drawText(times[i], xPoint[i],
marginBottom + 50, mPaint);
} else {
canvas.drawText(times[i], xPoint[i],
marginBottom + 50, mPaint);
}
}
times是自己定義的時間陣列:
private String[] times = {"5:00", "10:00", "15:00", "20:00", "24:00"};
X軸的時間繪製好後,接著我們來繪製Y軸,其實Y軸的思路和X軸一樣,也是分成5份,每份的計算方式為:螢幕的高度-距離底部的距離-距離上部的距離/5,程式碼如下;
int yHeight = (marginBottom - marginLeft) / 5;
由於5份每份的顏色值不一樣,所以我們要逐一進行處理:
for (int i
= 0; i
< xPoint.length; i++)
{
mPaint.setStrokeWidth(6);
int startY = marginBottom - yHeight * (i + 1);
int endY = marginBottom - yHeight * i;
switch (i) {
case 0:
mPaint.setColor(Color.GREEN);
break;
case 1:
mPaint.setColor(Color.YELLOW);
break;
case 2:
mPaint.setColor(0xFFFF7E00);
break;
case 3:
mPaint.setColor(Color.RED);
break;
case 4:
mPaint.setColor(0xFF8E1752);
break;
}
//繪製顏色線canvas.drawLine(marginLeft, startY,
marginLeft, endY, mPaint);
//繪製空氣汙染值canvas.drawText(atmosphereNum[i] + "", marginLeft
- 20,
startY, mPaint);
//繪製空氣汙染等級canvas.drawText(atmosphere[i], marginLeft
- 20,
endY - yHeight / 2, mPaint);
}
atmosphere是自己定義的汙染值等級陣列,atmosphere是自己定義的汙染值陣列:
private String[] atmosphere =
{"優", "好", "良", "中", "差"};
private int[] atmosphereNum =
{100, 200, 300, 400, 500};
再來看最後一塊,折線圖的繪製。其實每個點就是一個座標,繪製之前我們先把需要的資料整理一下:
private float[] broken =
{0f, 30f, 75f, 160f, 66f, 170f, 80f, 120f,130f,150f,138f,180f,200f,
220f,300f,235f,245f,260f,210f,270f,290f,270f,270f,250f,210f,180f,260f,280f,320f};
private int[] brokenTimes =
{0, 5, 10, 15, 20, 25, 30, 35,40,45,50,55,60,
65,70,75,80,85,90,95,100,105,110,115,120,125,130,135,140};
private Paint mPaint;
broken陣列,是空氣汙染值,下面的brokenTimes是時間點,我是這樣做的,X軸是24小時,共有1440分鐘,我分成了10分鐘一個點,也就是最多有144個點,brokenTimes裡的數值都是增的,畢竟時間走著走著不可能變小,broken陣列和brokenTimes陣列的長度一定要一樣大,因為,各個對應的值就是xy值。
縱軸是500個值,所以縱軸刻度值等於螢幕的高度-距離底部的距離-距離上部的距離/500,程式碼如下:
float brokenSizeY = (marginBottom - marginLeft) / 500;//得到縱軸刻度值
橫軸刻度值等於螢幕的寬度-距離左邊的距離-距離右邊的距離/144,程式碼如下:
float brokenSizeX = (this.getRight() - 20 - marginLeft) / 144;
繪製如下:
float lastX = brokenTimes[0]
* brokenSizeX + marginLeft, lastY = marginBottom - broken[0]
* brokenSizeY;
for (int a = 0; a
< broken.length; a++)
{
float height = marginBottom - broken[a]
* brokenSizeY;
float width = brokenTimes[a] * brokenSizeX + marginLeft;
canvas.drawCircle(width, height, 10, mPaint);
canvas.drawLine(lastX, lastY, width, height, mPaint);
lastX = width;
lastY = height;
}
lastX是記錄上一個X點,lastY是記錄上一個Y點。
經過以上的程式碼,我們就可以繪製出文章剛開始的圖片效果了,具體使用,也特別簡單,哪裡需要用,就在layout裡呼叫就可以了:
<com.ming.abner.chartline.BrokenLineView
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
詳細程式碼可關注我的微信公眾賬號HelloAbner(或掃描評論第一條二維碼關注),回覆“自定義折線圖”,完整的類就會發送給您。