Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義View------柱狀統計圖

Android自定義View------柱狀統計圖

編輯:關於Android編程

關於自定義View,相信多數開發者都已經非常熟悉了,網絡上的例子也非常多,各種炫酷吊炸天的自定義View也層出不窮。本文只是一個初級學習教程,對於初學者有參考價值。

下面正式進入主題。

本文采用自定義View的方式實現柱狀統計圖BarGraphView,實現了柱狀統計圖的基本功能,因為本身是為了學習自定義View,因此擴展性比較差,只能作為自定義View的參考。

上效果圖:

\

 

View顯示到屏幕上主要經過這三個過程

(1)Measure(測量)

首先View需要測量自身的大小,包括長和寬。 當View類的成員函數measure決定要重新測量當前View的寬度和高度之後,會去調用另外一個成員函數onMeasure來真正執行測量寬度和高度的操作。因此,自定義View大多都需要覆寫onMeasure方法來測量View的大小。onMeasure方法如下:

 

  @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

其中widthMeasureSpec和heightMeasureSpec兩個參數為父視圖的建議大小。 參數measureSpec的值其實是由兩部分內容來組成的,最高2位表示一個測量模式,而低30位表示一個寬度值或者高度值,測量模式有三種,分別是MeasureSpec.EXACTLY、MeasureSpec.UNSPECIFIED和MeasureSpec.AT_MOST,這裡就不講三種模式的區別了。在BarGraphView中將會參考這個兩個數值來確定BarGraphView的大小。

 

(2)Layout(布局)

這個過程只在View容器(ViewGroup及其子類)有用,因為非容器類View在屏幕中的位置操作由父控件來決定,所以不需要覆寫onLayout()方法。

(3)Draw(繪制)

最後繪制View的過程,在這個過程裡主要通過Paint對象在Canvas上面繪制相應圖像,最終把View展現在屏幕上。 對於自定義View來說,通常需要覆寫onDraw()方法繪制View。

 

    @Override
    public void onDraw(Canvas canvas) {
    }
該方法提供了一塊畫布,我們只需要創建一個畫筆在畫布上繪圖案即可。

 

 

好了,了解了上述過程,接下來我們開始實現BarGraphView。

BarGraphView主要代碼集中在Draw的過程,通過onDraw方法把統計圖繪制到屏幕上來。

經過分析,把柱狀圖分為以下幾部分

1.橫/縱坐標軸

2.橫/縱坐標軸刻度線

3.橫/縱坐標軸刻度值

4.橫/縱坐標軸箭頭

5.標題

6.柱狀圖

針對不同部分利用drawLine()(畫直線)、drawText()(畫文字)、drawPath()(畫多邊形)以及drawRect()(畫矩形)的方法分別繪制相應圖案。

以下是BarGraphView類代碼,可以直接看注釋。

 

package com.eleven.demo.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;

import com.eleven.demo.R;

/**
 * Created by Eleven on 2015/5/3.
 */
public class BarGraphView extends View {

    private final String TAG = BarGraphView.class.getName();
    //畫筆
    private Paint mPaint;
    //標題
    private String title;
    //標題顏色
    private int titleColor;
    //標題大小
    private float titleSize;
    //X坐標軸最大值
    private float maxAxisValueX = 900;
    //X坐標軸刻度線數量
    private int axisDivideSizeX = 9;
    //Y坐標軸最大值
    private float maxAxisValueY = 700;
    //Y坐標軸刻度線數量
    private int axisDivideSizeY = 7;
    //視圖寬度
    private int width;
    //視圖高度
    private int height;
    //坐標原點位置
    private final int originX = 100;
    private final int originY = 800;
    //柱狀圖數據
    private int columnInfo[][];

    public BarGraphView(Context context, AttributeSet attrs) {
        super(context, attrs);
        //創建畫筆
        mPaint = new Paint();
        //獲取配置的屬性值
        TypedArray mArray = context.obtainStyledAttributes(attrs, R.styleable.BarGraphView);
        title = mArray.getString(R.styleable.BarGraphView_barGraph_title);
        titleColor = mArray.getColor(R.styleable.BarGraphView_barGraph_titleColor, Color.BLACK);
        titleSize = mArray.getDimension(R.styleable.BarGraphView_barGraph_titleSize, 36);
    }

    /**
     * 設置X軸的最大值及刻度線數量(包括0坐標刻度)
     *
     * @param maxValue   X軸的最大值
     * @param divideSize 刻度線數量
     */
    public void setAxisX(float maxValue, int divideSize) {
        maxAxisValueX = maxValue;
        axisDivideSizeX = divideSize;
    }

    /**
     * 設置Y軸的最大值及刻度線數量(包括0坐標刻度)
     *
     * @param maxValue   Y軸的最大值
     * @param divideSize 刻度線數量
     */
    public void setAxisY(float maxValue, int divideSize) {
        maxAxisValueY = maxValue;
        axisDivideSizeY = divideSize;
    }

    /**
     * 設置柱狀圖數據
     *
     * @param columnInfo
     */
    public void setColumnInfo(int[][] columnInfo) {
        this.columnInfo = columnInfo;
    }

    @Override
    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = MeasureSpec.getSize(widthMeasureSpec) - 200;
        height = MeasureSpec.getSize(heightMeasureSpec) - 800;
    }

    @Override
    public void onDraw(Canvas canvas) {
        drawAxisX(canvas, mPaint);
        drawAxisY(canvas, mPaint);
        drawAxisScaleMarkX(canvas, mPaint);
        drawAxisScaleMarkY(canvas, mPaint);
        drawAxisArrowsX(canvas, mPaint);
        drawAxisArrowsY(canvas, mPaint);
        drawAxisScaleMarkValueX(canvas, mPaint);
        drawAxisScaleMarkValueY(canvas, mPaint);
        drawColumn(canvas, mPaint);
        drawTitle(canvas, mPaint);
    }

    /**
     * 繪制橫坐標軸(X軸)
     *
     * @param canvas
     * @param paint
     */
    private void drawAxisX(Canvas canvas, Paint paint) {
        paint.setColor(Color.BLACK);
        //設置畫筆寬度
        paint.setStrokeWidth(5);
        //設置畫筆抗鋸齒
        paint.setAntiAlias(true);
        //畫橫軸(X)
        canvas.drawLine(originX, originY, originX + width, originY, paint);
    }

    /**
     * 繪制縱坐標軸(Y軸)
     *
     * @param canvas
     * @param paint
     */
    private void drawAxisY(Canvas canvas, Paint paint) {
        //畫豎軸(Y)
        canvas.drawLine(originX, originY, originX, originY - height, paint);//參數說明:起始點左邊x,y,終點坐標x,y,畫筆
    }


    /**
     * 繪制橫坐標軸刻度線(X軸)
     *
     * @param canvas
     * @param paint
     */
    private void drawAxisScaleMarkX(Canvas canvas, Paint paint) {
        float cellWidth = width / axisDivideSizeX;
        for (int i = 0; i < axisDivideSizeX - 1; i++) {
            canvas.drawLine(cellWidth * (i + 1) + originX, originY, cellWidth * (i + 1) + originX, originY - 10, paint);
        }
    }

    /**
     * 繪制縱坐標軸刻度線(Y軸)
     *
     * @param canvas
     * @param paint
     */
    private void drawAxisScaleMarkY(Canvas canvas, Paint paint) {
        float cellHeight = height / axisDivideSizeY;
        for (int i = 0; i < axisDivideSizeY - 1; i++) {
            canvas.drawLine(originX, (originY - cellHeight * (i + 1)), originX + 10, (originY - cellHeight * (i + 1)), paint);
        }
    }

    /**
     * 繪制橫坐標軸刻度值(X軸)
     *
     * @param canvas
     * @param paint
     */
    private void drawAxisScaleMarkValueX(Canvas canvas, Paint paint) {
        //設置畫筆繪制文字的屬性
        paint.setColor(Color.GRAY);
        paint.setTextSize(28);
        paint.setFakeBoldText(true);

        float cellWidth = width / axisDivideSizeX;
        float cellValue = maxAxisValueX / axisDivideSizeX;
        for (int i = 1; i < axisDivideSizeX; i++) {
            canvas.drawText(String.valueOf(cellValue * i), cellWidth * i + originX - 35, originY + 30, paint);
        }
    }

    /**
     * 繪制縱坐標軸刻度值(Y軸)
     *
     * @param canvas
     * @param paint
     */
    private void drawAxisScaleMarkValueY(Canvas canvas, Paint paint) {
        float cellHeight = height / axisDivideSizeY;
        float cellValue = maxAxisValueY / axisDivideSizeY;
        for (int i = 1; i < axisDivideSizeY; i++) {
            canvas.drawText(String.valueOf(cellValue * i), originX - 80, originY - cellHeight * i + 10, paint);
        }
    }

    /**
     * 繪制橫坐標軸箭頭(X軸)
     *
     * @param canvas
     * @param paint
     */
    private void drawAxisArrowsX(Canvas canvas, Paint paint) {
        //畫三角形(X軸箭頭)
        Path mPathX = new Path();
        mPathX.moveTo(originX + width + 30, originY);//起始點
        mPathX.lineTo(originX + width, originY - 10);//下一點
        mPathX.lineTo(originX + width, originY + 10);//下一點
        mPathX.close();
        canvas.drawPath(mPathX, paint);
    }

    /**
     * 繪制縱坐標軸箭頭(Y軸)
     *
     * @param canvas
     * @param paint
     */
    private void drawAxisArrowsY(Canvas canvas, Paint paint) {
        //畫三角形(Y軸箭頭)
        Path mPathX = new Path();
        mPathX.moveTo(originX, originY - height - 30);//起始點
        mPathX.lineTo(originX - 10, originY - height);//下一點
        mPathX.lineTo(originX + 10, originY - height);//下一點
        mPathX.close();
        canvas.drawPath(mPathX, paint);
    }

    /**
     * 繪制柱狀圖
     *
     * @param canvas
     * @param paint
     */
    private void drawColumn(Canvas canvas, Paint paint) {
        if(columnInfo == null)
            return;
        float cellWidth = width / axisDivideSizeX;
        for (int i = 0; i < columnInfo.length; i++) {
            paint.setColor(columnInfo[i][1]);
            float leftTopY = originY - height * columnInfo[i][0] / maxAxisValueY;
            canvas.drawRect(originX + cellWidth * (i + 1), leftTopY, originX + cellWidth * (i + 2), originY, mPaint);//左上角x,y右下角x,y,畫筆
        }
    }

    /**
     * 繪制標題
     *
     * @param canvas
     * @param paint
     */
    private void drawTitle(Canvas canvas, Paint paint) {

        //畫標題
        if (title != null) {
            //設置畫筆繪制文字的屬性
            mPaint.setColor(titleColor);
            mPaint.setTextSize(titleSize);
            mPaint.setFakeBoldText(true);
            canvas.drawText(title, 300, originY + 150, paint);
        }
    }
}


 

 

 

MainActivity的布局文件:

 



    


MainActivity中使用

 

 

public class MainActivity extends ActionBarActivity {
    private BarGraphView mBarGraphView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView(){
        mBarGraphView = (BarGraphView)findViewById(R.id.custom_view);
        mBarGraphView.setAxisX(900, 9);
        mBarGraphView.setAxisY(700,7);

        int columnInfo[][] = new int[][]{{600, Color.BLUE},{500, Color.GREEN},{400, Color.RED},{300, Color.BLUE},
                {500, Color.YELLOW},{300, Color.LTGRAY},{200, Color.BLUE}};
        mBarGraphView.setColumnInfo(columnInfo);
    }


 


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved