1. 程式人生 > >Android自定義控制元件之《折線圖的繪製》

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("

帝都空氣質量趨勢圖(author:AbnerMing)"10050mPaint);
}

setTypeface()是用來設定字型,這裡我設定的是,宋體加粗

Typeface blodFont = Typeface.create("宋體"Typeface.BOLD);

在onDraw()方法裡繪製XY軸:

為了使整體看起來稍稍美觀,我們繪製的時候,儘量與上下左右保持一定的距離,這裡我設定的是距離底部為this.getBottom()-100,距離左邊為100,程式碼如下:

int marginBottom = this.getBottom() - 100;
int 
marginLeft = 100

;

初始化XY軸:

//初始化XmPaint.setColor(Color.WHITE);
canvas.drawLine(marginLeftmarginLeftmarginLeftmarginBottommPaint);
//初始化YmPaint.setStrokeWidth(6);
canvas.drawLine(marginLeftmarginBottom, this.getRight() - 20marginBottommPaint);

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 = 0a < 5a++) {
    xLine += xWidth;
    
xPoint[a] = xLine;
}

xPoint就是各個時間點的X軸座標,顯然Y軸是不變的,那麼我們就可以如下繪製;

for (int i = 0i < xPoint.lengthi++) {
    mPaint.setColor(Color.parseColor("#FF00FF"));
    
mPaint.setTextSize(40);
    
mPaint.setTypeface(font);
    
mPaint.setTextAlign(Paint.Align.RIGHT);
    if 
(i == 0) {
        canvas.drawText("0"marginLeft,
                
marginBottom + 50mPaint);
        
canvas.drawText(times[i]xPoint[i],
                
marginBottom + 50mPaint);
    
else {
        canvas.drawText(times[i]xPoint[i],
                
marginBottom + 50mPaint);

    
}
}

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 = 0i < xPoint.lengthi++) {
    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(marginLeftstartY,
            
marginLeftendYmPaint);
    
//繪製空氣汙染值canvas.drawText(atmosphereNum[i] + ""marginLeft - 20,
            
startYmPaint);
    
//繪製空氣汙染等級canvas.drawText(atmosphere[i]marginLeft - 20,
            
endY - yHeight / 2mPaint);
}

atmosphere是自己定義的汙染值等級陣列,atmosphere是自己定義的汙染值陣列:

private String[] atmosphere = {""""""""""};
private int[] atmosphereNum = {100200300400500};

再來看最後一塊,折線圖的繪製。其實每個點就是一個座標,繪製之前我們先把需要的資料整理一下:

private float[] broken = {0f30f75f160f66f170f80f120f,130f,150f,138f,180f,200f,
        
220f,300f,235f,245f,260f,210f,270f,290f,270f,270f,250f,210f,180f,260f,280f,320f};
private int
[] brokenTimes = {05101520253035,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 + marginLeftlastY = marginBottom - broken[0] * brokenSizeY;
for 
(int a = 0a < broken.lengtha++) {
    float height = marginBottom - broken[a] * brokenSizeY;
    float 
width = brokenTimes[a] * brokenSizeX + marginLeft;
    
canvas.drawCircle(widthheight10mPaint);

    
canvas.drawLine(lastXlastYwidthheightmPaint);
    
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(或掃描評論第一條二維碼關注),回覆“自定義折線圖”,完整的類就會發送給您。