Android圖表繪制

由于最新項目需要用到圖表顯示數據,所以參考網上的資源,寫了一個demo,主要是通過在Activity發送不同的數據到view里面刷新顯示,每發送一次數據,就顯示幾個隨機數到view顯示。
顯示效果如圖:


這里寫圖片描述

代碼注釋比較詳細,就不做太多說明了。
ZywChartView.java

@SuppressLint("DrawAllocation")
public class ZywChartView extends View {

    private String TAG = "ZywChartView";
    // 默認邊距
    
    private float Margin = 40;
    
    //圓半徑
    private int circleRadius = 8;
    
    // X,Y軸的單位長度
    private float Xscale = 20;
    private float Yscale = 20;
    
    //X軸第1個節點到最后1個節點的長度
    private float xLength;
    //Y軸第1個節點到最后1個節點的長度
    private float yLength;
    
    //X軸第1個節點的偏移量
    private float xFirstPointOffset;
    
    //y軸顯示的節點間隔距離
    private int yScaleForData = 5;

    //畫線顏色
    private int lineColor = this.getResources().getColor(R.color.saswell_yellow);

    // 原點坐標
    private float Xpoint;
    private float Ypoint;
    
    private String yUnit = "";
    private String xUnit = "";

    // X,Y軸上面的顯示文字
    private String[] Xlabel = { "1", "2", "3", "4", "5", "6", "7"};
    private String[] Ylabel = { "0", "1", "2", "3", "4", "5", "6", "7", "8",
            "9", "10" };
    
    private final static int Y_SCALE_FOR_DATA_DAY = 5; 
    private final static int Y_SCALE_FOR_DATA_WEEK = 2; 
    private final static int Y_SCALE_FOR_DATA_MOUNTH = 2; 
    
    // 曲線數據
    private int[] Data = {5, 5, 5, 5, 5, 5, 5};
    
    public ZywChartView(Context context, String[] xlabel, String[] ylabel, int[] data) {
        super(context);
        this.Xlabel = xlabel;
        this.Ylabel = ylabel;
        this.Data = data;
    }

    public ZywChartView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        Log.e(TAG,"ZywChartView(Context context, AttributeSet attrs, int defStyleAttr)");
    }

    public ZywChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        
        init();
        xFirstPointOffset = 2 * this.Margin;
        Log.e(TAG,"ZywChartView(Context context, AttributeSet attrs)");
    }

    public ZywChartView(Context context) {
        super(context);
        Log.e(TAG,"ZywChartView(Context context)");
    }

    /**
     * 設置顯示的數據
     * @param str要顯示的數據字符串
     * @author zyw
     */
    public void setData(String str){
        String[] tempData;
        tempData = str.split(",");  
        int yDataLength = 0;
        Log.e(TAG, "str = " + str);
        Data = new int[tempData.length];
        Xlabel = new String[tempData.length];
        
        if(tempData.length >= 28){
            yScaleForData = Y_SCALE_FOR_DATA_MOUNTH;
            yDataLength = 25;
            xUnit = getResources().getString(R.string.x_unit_month);
            yUnit = getResources().getString(R.string.y_unit_month);
        }else if(tempData.length >= 12){
            yScaleForData = Y_SCALE_FOR_DATA_DAY;
            yDataLength = 61;
            xUnit = getResources().getString(R.string.x_unit_day);
            yUnit = getResources().getString(R.string.y_unit_day);
        }else{
            yScaleForData = Y_SCALE_FOR_DATA_WEEK;
            yDataLength = 25;
            xUnit = getResources().getString(R.string.x_unit_week);
            yUnit = getResources().getString(R.string.y_unit_week);
        }
        
        Ylabel = new String[yDataLength];
        for(int i = 0; i < yDataLength; i++){
            Ylabel[i] = Integer.toString(i);
            //Log.e(TAG,"Ylable[" + i +  "]" + Ylabel[i]);
        }

        for(int i = 0; i < tempData.length; i++){
            Data[i] = Integer.parseInt(tempData[i]);
            //Log.e(TAG,"Data[" + i +  "]" + Data[i]);
            Xlabel[i] = Integer.toString(i + 1);
            Log.e(TAG,"Xlable[" + i +  "]" + Xlabel[i]);
        }
        
        invalidate();
    }

    // 初始化數據
    public void init() {
        Xpoint = this.Margin;
        Log.e(TAG, "this.getHeight() == " + this.getHeight());
        Ypoint = this.getHeight() - this.Margin;
        Xscale = (this.getWidth() - 4 * this.Margin) / (this.Xlabel.length);
        Yscale = (this.getHeight() - 3 * this.Margin) / (this.Ylabel.length);
        
        xLength = this.getWidth() - (4 * this.Margin);
        yLength = this.getHeight() - (2 * this.Margin);
        
        xFirstPointOffset = Xscale;
    }

    public float getMargin() {
        return Margin;
    }

    public void setMargin(int margin) {
        Margin = margin;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawColor(Color.BLACK);
        Log.e(TAG, "onDraw");
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setColor(lineColor);
        paint.setStrokeWidth(3);
        init();
        this.drawXLine(canvas, paint);
        this.drawYLine(canvas, paint);
        this.drawDashPath(canvas);
        this.drawData(canvas);
        this.drawXUnit(canvas);
        this.drawYUnit(canvas);
    }

    //畫虛線
    private void drawDashPath(Canvas canvas) {
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(lineColor);
        paint.setStrokeWidth(3);
        Path path = new Path();
        //繪制長度為10的實線,再繪制長度為10的空白,再繪制長度為10的實線,再回執長度為10的空白,依次重復,1為偏移量
        PathEffect effects = new DashPathEffect(new float[] { 10, 10, 10, 10}, 1);
        paint.setPathEffect(effects);

        // 縱向線
        for (int i = 0; i * Xscale < xLength; i++) {
            float startX = Xpoint + i * Xscale + xFirstPointOffset;
            float startY = Ypoint;
            float stopY = calY(Data[i]);
            path.moveTo(startX, startY);
            path.lineTo(startX, stopY);
            canvas.drawPath(path, paint);
        }
    }

    private void drawXUnit(Canvas canvas) {
        Paint p = new Paint();
        p.setAntiAlias(true);
        p.setColor(lineColor);
        p.setStrokeWidth(2);
        p.setTextSize(this.Margin / 2);
        canvas.drawText(xUnit, this.getWidth() - this.Margin * 2 + this.Margin / 4, Ypoint + this.Margin / 5, p);
    }
    
    private void drawYUnit(Canvas canvas) {
        Paint p = new Paint();
        p.setAntiAlias(true);
        p.setColor(lineColor);
        p.setStrokeWidth(2);
        p.setTextSize(this.Margin / 2);
        canvas.drawText(yUnit, this.Margin / 2, this.Margin / 2, p);
    }
    
    // 畫橫縱軸
    private void drawXLine(Canvas canvas, Paint p) {
        canvas.drawLine(Xpoint, Ypoint, this.getWidth() - this.Margin * 2, Ypoint,
                p);
        canvas.drawLine(this.getWidth() - this.Margin * 2, Ypoint, this.getWidth()
                - this.Margin * 2 - this.Margin / 3, Ypoint - this.Margin / 3, p);
        canvas.drawLine(this.getWidth() - this.Margin * 2, Ypoint, this.getWidth()
                - this.Margin * 2 - this.Margin / 3, Ypoint + this.Margin / 3, p);
    }
    
    private void drawYLine(Canvas canvas, Paint p) {
        canvas.drawLine(Xpoint, Ypoint, this.Margin, this.Margin, p);
        canvas.drawLine(Xpoint, this.Margin, Xpoint - Xpoint / 3, this.Margin
                + this.Margin / 3, p);
        canvas.drawLine(Xpoint, this.Margin, Xpoint + Xpoint / 3, this.Margin
                + this.Margin / 3, p);
    }

    // 畫數據
    private void drawData(Canvas canvas) {
        Paint p = new Paint();
        p.setAntiAlias(true);
        p.setColor(lineColor);
        p.setStrokeWidth(3);
        p.setTextSize(this.Margin / 2);
        //橫向
        for (int i = 0; i * Xscale < xLength; i++) {
            float startX = Xpoint + i * Xscale + xFirstPointOffset;
            canvas.drawText(this.Xlabel[i], startX - this.Margin / 4,
                    this.getHeight() - this.Margin / 4, p);
            canvas.drawCircle(startX, calY(Data[i]), circleRadius, p);
            if(i != 0){
                canvas.drawLine(Xpoint + (i - 1) * Xscale + xFirstPointOffset, calY(Data[i-1]), startX, calY(Data[i]), p);
            }
        }
        
        //縱向
        for (int i = 0; (yLength - i * Yscale) >= this.Margin; i += yScaleForData) {
            float startY = Ypoint - i * Yscale;
            canvas.drawText(this.Ylabel[i], this.Margin / 4, startY
                    + this.Margin / 4, p);
        }
    }

    /**
     * 
     * @param y  
     * @return
     */
    private float calY(int y){ 
        int y0 = 0 ;
        int y1 = 0 ;
        //  Log.i("zzzz", "y:"+y);
        try{
            y0 = Integer.parseInt(Ylabel[0]);
            //      Log.i("zzzz", "y0"+y0);
            y1 = Integer.parseInt(Ylabel[1]);
            //      Log.i("zzzz","y1"+y1);
        }catch(Exception e){
            //      Log.i("zzzz", "string changed is err");
            return 0;
        }
        try{
            //      Log.i("zzzz", "返回數據"+(Ypoint-(y-y0)*Yscale/(y1-y0)) );
            return Ypoint - ((y-y0) * Yscale/(y1-y0));
        }catch(Exception e){
            //  Log.i("zzzz", "return is err");
            return 0;
        }
    }

}

EnergyConsumptionActivity.java

public class EnergyConsumptionActivity extends Activity{
    private int randomNum;
    private RadioGroup rgModeSelect;
    private RadioButton rbDayMode,rbWeekMode,rbMonthMode;
    private String TAG = "MainActivity";
    private Button btnSetData,btnTitle;
    private ZywChartView myView;
    private String strData;
    private int mode,randomDataLength = 10;
    private final static int DAY_MODE = 1;
    private final static int WEEK_MODE = 2;
    private final static int MONTH_MODE = 3;

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

    private OnClickListener onClickListener = new OnClickListener() {
        
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.btnSetData:
                Log.e("ZYW", "set Data.");
                sendData(mode);
                break;
                
            case R.id.title_back:
                Log.e(TAG,"finish.");
                finish();
                break;
                
            default:
                break;
            }
            
        }
    };
    
    private OnCheckedChangeListener checkedChangeListener = new OnCheckedChangeListener() {

        @Override
        public void onCheckedChanged(RadioGroup group, int checkedId) {
            try {
                switch(checkedId){
                case R.id.rbDayMode:
                    mode = DAY_MODE;
                    randomDataLength = 60;
                    break;
                case R.id.rbWeekMode:
                    mode = WEEK_MODE;
                    randomDataLength = 24;
                    break;
                case R.id.rbmonthMode:
                    mode = MONTH_MODE;
                    randomDataLength = 24;
                    break;
                }
                sendData(mode);
                Log.e(TAG, "mode = " + mode);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };

    /**
     * 在0-randomDataLength中生成一個隨機數
     * @return 隨機生成的數字組合字符串: data1,data2,data3,...dataN
     */
    public String getRandomNum(int mode){
        String strRandomNum = "";
        int maxI = 7;
        //根據模式(天、周、月)確定要繪制的折線圖
        switch (mode) {
        case DAY_MODE:
            maxI = 12;
            break;

        case WEEK_MODE:
            maxI = 7;
            break;

        case MONTH_MODE:
            maxI = 30;
            break;

        default:
            Log.e(TAG, "mode is error");
            break;
        }

        for(int i = 0; i < maxI; i++){
            //在0-randomDataLength中生成一個隨機數
            randomNum = (int) (Math.random()*randomDataLength);
            //Log.e(TAG, "randomNum ==" + randomNum);
            if(i != (maxI - 1)){
                strRandomNum += randomNum + ",";
            }
            else{
                strRandomNum += randomNum;
            }
        }
        Log.e(TAG, "strRandomNum ==" + strRandomNum);
        return strRandomNum;
    }

    /**
     * 發送數據
     * @param mode
     */
    public void sendData(int mode){
        strData = getRandomNum(mode);
        myView.setData(strData);
    }

    public void init(){
        btnSetData = (Button) findViewById(R.id.btnSetData);
        btnTitle = (Button) findViewById(R.id.title_back);
        myView = (ZywChartView) findViewById(R.id.myView);
        rbDayMode = (RadioButton) findViewById(R.id.rbDayMode);
        rbWeekMode = (RadioButton) findViewById(R.id.rbWeekMode);
        rbMonthMode = (RadioButton) findViewById(R.id.rbmonthMode);
        rgModeSelect = (RadioGroup) findViewById(R.id.rgModeSelect);
        
        rgModeSelect.setOnCheckedChangeListener(checkedChangeListener);
        btnTitle.setOnClickListener(onClickListener);
        btnSetData.setOnClickListener(onClickListener);
        
        rbDayMode.setChecked(true);
    }
}

demo下載地址:http://download.csdn.net/detail/oqinyou/9492870

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,076評論 25 708
  • 中學同學聚會,大家不外乎說著一些不著痛癢的奉承話,互相吹捧,也互相揶揄:誰升官了,誰發財了,誰離婚了。我只在一旁靜...
    jane持閱讀 764評論 13 18
  • 決定加入行動營,我覺得自己是一種初生牛犢不怕虎的傻勁。小灶群快要結營了,心里很不舍,希望小灶群在我的生命中留下更深...
    愛寫作的圈圈閱讀 278評論 0 6
  • 人生就像一杯茶,不會苦一輩子,但總會苦一陣子。 時間又像一張網,我們把它撒在哪,收獲就在哪里! 奔波是快樂,它讓我...
    旭小旦閱讀 134評論 0 0
  • 走過荒涼的街道,我不習慣慢跑,我習慣黑暗中的靜悄悄,遠離熱鬧,遠離紛擾,一個人是一種美好。一個女人路過輕飄飄,難道...
    李一十八閱讀 386評論 0 0