Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 安卓自定義控件之不可滑動的折線圖

安卓自定義控件之不可滑動的折線圖

編輯:關於Android編程

代碼在注釋中,與柱狀圖的實現類似

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


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * Created by wangliang on 0013/2016/9/13.
 * 思路:每傳遞一次坐標名稱則更新一次視圖,坐標的傳遞采用動態計算的方法,當更改坐標軸名稱的時候,所有視圖清空進行重繪,柱狀圖顯示數量由所傳遞的徐州的名稱決定
 */
public class BrokenLineGrapNoScrollView extends View {

    private Context context;
    private final String TAG = "HistogramNoScrollView";
    private Integer defaultAxisColor = Color.BLACK;
    private Integer defaultAxisWidth;

    private List xAxisListNames;
    private List yAxisListNames;
    private List xAxisCoordinateList;//所有x軸基准點坐標
    private List yAxisCoordinateList;//所有y軸基准點坐標
    private List xAxisTextCoordinateList;//所有x軸文字坐標
    private List yAxisTextCoordinateList;//所有y軸文字坐標
    private List listAllNoAxisCoordinate;//除軸上坐標之外的其他柱狀圖的坐標

    private Paint xAxisTextPaint;//x軸文字畫筆
    private Paint yAxisTextPaint;//y軸文字畫筆
    private Paint xAxisPaint;//x軸畫筆
    private Paint yAxisPaint;//y軸畫筆
    private Paint brokenLineGrapPaint;//柱狀圖畫筆
    private Paint averageValuePaint;//平均值線
    private Path averageValuePath;//平均值線

    private Integer axisTextColor;
    private Integer axisTextSize;

    private Integer defaultBetweenXAxisAndTextSpace;
    private Integer defaultBetweenYAxisAndTextSpace;
    private int xCoordinateDistance;//x軸每段的寬度

    private Double maxValue;//柱狀圖所能顯示的最大值
    private Double averageValue;//柱狀圖的平均值
    private Map histogramValue;//柱狀圖所喲柱子的值
    private float histogramShowFanWei;//柱狀圖所能顯示的范圍

    private Boolean whetherShowXAxis;//是否顯示y軸
    private Boolean whetherShowYAxis;//是否顯示x軸
    private Boolean whetherShowAverageValue;//是否顯示柱狀圖平均值

    public BrokenLineGrapNoScrollView(Context context) {
        super(context);
        initSetting(context,null);
    }

    public BrokenLineGrapNoScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initSetting(context,null);
    }

    public BrokenLineGrapNoScrollView(Context context, AttributeSet attrs, Integer defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initSetting(context,defStyleAttr);
    }

    private void initSetting(Context context, Integer defStyleAttr) {
        this.context = context;
        defaultBetweenXAxisAndTextSpace = 0;
        defaultBetweenYAxisAndTextSpace = 0;
        defaultAxisColor = Color.BLACK;
        defaultAxisWidth = context.getResources().getDimensionPixelOffset(R.dimen.common_dp_0_1);
        axisTextColor = Color.RED;
        axisTextSize = context.getResources().getDimensionPixelOffset(R.dimen.default_text_medium);

        xAxisTextPaint = new Paint();
        xAxisTextPaint.setTextSize(axisTextSize);
        xAxisTextPaint.setColor(axisTextColor);

        yAxisTextPaint = new Paint();
        yAxisTextPaint.setTextSize(axisTextSize);
        yAxisTextPaint.setColor(axisTextColor);

        xAxisPaint = new Paint();
        xAxisPaint.setColor(defaultAxisColor);
//        xAxisPaint.setStrokeWidth(defaultAxisWidth);
        xAxisPaint.setAntiAlias(true);

        yAxisPaint = new Paint();
        yAxisPaint.setColor(defaultAxisColor);
//        yAxisPaint.setStrokeWidth(defaultAxisWidth);
        yAxisPaint.setAntiAlias(true);


        brokenLineGrapPaint = new Paint();
        brokenLineGrapPaint.setColor(Color.BLACK);
        brokenLineGrapPaint.setTextSize(axisTextSize);
        brokenLineGrapPaint.setAntiAlias(true);

        averageValuePaint = new Paint ( ) ;
        averageValuePaint.setColor ( Color.BLACK ) ;
        //設置畫直線格式
        averageValuePaint.setStyle ( Paint.Style.STROKE ) ;
        /**設置虛線效果
         * 裡邊的float數組的意思是:先畫長度為3的實線,再間隔長度為2的空白,之後一直重復這個單元。
         * 這個數組的長度只要大於等於2就行,你可以設置多個數值,產生不同效果,最後這個0指的是與起始位置的偏移量。
         */
        averageValuePaint.setPathEffect ( new DashPathEffect( new float [ ] { 3, 2 }, 0 ) ) ;

    }

    /**
     * 設置x軸坐標文字
     * @param xAxisListNames
     * @return
     */
    public BrokenLineGrapNoScrollView setXAxisNames(List xAxisListNames, boolean whetherShowXAxis){
        this.xAxisListNames = xAxisListNames;
        this.whetherShowXAxis = whetherShowXAxis;
        xAxisCoordinateList = null;//所有x軸基准點坐標
        yAxisCoordinateList = null;//所有y軸基准點坐標
        xAxisTextCoordinateList = null;//所有x軸文字坐標
        listAllNoAxisCoordinate = null;//除軸上坐標之外的其他柱狀圖的坐標
        return this;
    }

    /**
     * 設置y軸坐標文字
     * @param yAxisListNames
     * @return
     */
    public BrokenLineGrapNoScrollView setYAxisNames(List yAxisListNames, boolean whetherShowYAxis){
        this.yAxisListNames = yAxisListNames;
        this.whetherShowYAxis = whetherShowYAxis;
        yAxisCoordinateList = null;//所有y軸基准點坐標
        yAxisTextCoordinateList = null;
        listAllNoAxisCoordinate = null;//除軸上坐標之外的其他柱狀圖的坐標
        return this;
    }

    /**
     * 設置柱狀圖所要顯示的最大值以及平均值
     * @param maxValue 最大值
     * @param averageValue 平均值
     * @param whetherShowAverageValue 是否顯示平均值線
     * @return
     */
    public BrokenLineGrapNoScrollView setMaxValueAndAverageValue(double maxValue, double averageValue, boolean whetherShowAverageValue){
        this.maxValue = maxValue;
        this.averageValue = averageValue;
        this.whetherShowAverageValue = whetherShowAverageValue;
        listAllNoAxisCoordinate = null;//除軸上坐標之外的其他柱狀圖的坐標
        return this;
    }

    public BrokenLineGrapNoScrollView setHistogramValue(Map histogramValue){
        this.histogramValue = histogramValue;
        listAllNoAxisCoordinate = null;//除軸上坐標之外的其他柱狀圖的坐標
        return this;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if(xAxisTextCoordinateList == null){
            getXAxisTextCoordinateList();
        }
        if(xAxisCoordinateList == null){
            getXAxisCoordinateList();
        }
        if(yAxisTextCoordinateList == null){
            getYAxisTextCoordinateList();
        }
        if(yAxisCoordinateList == null){
            getYAxisCoordinateList();
        }

        if(listAllNoAxisCoordinate == null){
            getListAllNoAxisCoordinate();
        }

        /**
         * 獲取所要畫的虛線的path
         */
        if(averageValuePath == null && maxValue != null && averageValue != null){
            histogramShowFanWei = getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace;
            averageValuePath = new Path();
            averageValuePath.moveTo(0, (float) (histogramShowFanWei - histogramShowFanWei * (averageValue / maxValue)));
            averageValuePath.lineTo(getWidth() - defaultBetweenYAxisAndTextSpace, (float) (histogramShowFanWei - histogramShowFanWei * (averageValue / maxValue)));
        }

        /**
         * 畫x軸
         */
        if(xAxisTextCoordinateList.size() > 0 && whetherShowXAxis) {
            canvas.drawLine(getX() - defaultBetweenYAxisAndTextSpace,
                    getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace,
                    getWidth(),
                    getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace
                    , xAxisPaint);
        }

        /**
         * 畫y軸
         */
        if(yAxisTextCoordinateList.size() > 0 && whetherShowYAxis) {
            canvas.drawLine(getX() - defaultBetweenYAxisAndTextSpace,
                    0,
                    getX() - defaultBetweenYAxisAndTextSpace,
                    getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace
                    , xAxisPaint);
        }

        /**
         * 畫虛線,代表著平均值
         */
        if(listAllNoAxisCoordinate.size() > 0  && whetherShowAverageValue){
            canvas.drawPath(averageValuePath,averageValuePaint);
        }

        /**
         * 繪制x軸上的坐標刻度文字
         */
        for(int  i = 0 ; i < xAxisTextCoordinateList.size() ; i++){
            canvas.drawText(xAxisTextCoordinateList.get(i).getCoordinatename(),
                    xAxisTextCoordinateList.get(i).getxCoordinate(),
                    xAxisTextCoordinateList.get(i).getyCoordinate(),
                    xAxisTextPaint);
        }

        /**
         * 繪制折線圖
         */
        for(int  i = 0 ; i < listAllNoAxisCoordinate.size() ; i++){
            float textWidth = brokenLineGrapPaint.measureText(listAllNoAxisCoordinate.get(i).getCoordinatename());
            Integer circleRadius = null;
            if(circleRadius == null){
                circleRadius = 10;
            }
            canvas.drawCircle(listAllNoAxisCoordinate.get(i).getxCoordinate(),
                    listAllNoAxisCoordinate.get(i).getyCoordinate(),circleRadius,brokenLineGrapPaint);

            if(listAllNoAxisCoordinate.get(i).getxCoordinate() <= getX() + defaultBetweenYAxisAndTextSpace){
                canvas.drawText(listAllNoAxisCoordinate.get(i).getCoordinatename(),
                        listAllNoAxisCoordinate.get(i).getxCoordinate(),
                        listAllNoAxisCoordinate.get(i).getyCoordinate() - circleRadius - 10 ,brokenLineGrapPaint);
            }else if(listAllNoAxisCoordinate.get(i).getxCoordinate() >= getWidth()){
                canvas.drawText(listAllNoAxisCoordinate.get(i).getCoordinatename(),
                        listAllNoAxisCoordinate.get(i).getxCoordinate() - textWidth,
                        listAllNoAxisCoordinate.get(i).getyCoordinate() - circleRadius - 10 ,brokenLineGrapPaint);
            }else {
                canvas.drawText(listAllNoAxisCoordinate.get(i).getCoordinatename(),
                        listAllNoAxisCoordinate.get(i).getxCoordinate() - textWidth / 2,
                        listAllNoAxisCoordinate.get(i).getyCoordinate() - circleRadius - 10 ,brokenLineGrapPaint);
            }

            if(i > 0){
                canvas.drawLine(listAllNoAxisCoordinate.get(i - 1).getxCoordinate(),
                        listAllNoAxisCoordinate.get(i - 1).getyCoordinate(),
                        listAllNoAxisCoordinate.get(i).getxCoordinate(),
                        listAllNoAxisCoordinate.get(i).getyCoordinate(),brokenLineGrapPaint);
            }
        }

    }

    private Paint.FontMetrics fm;
    /**
     * 根據文字獲得文字相對於x軸的坐標
     * @param text
     * @param xCoordinateDistance
     * @return
     */
    private float[] getXtextCoordinate(String text,float xCoordinateDistance){
        float[] xy = new float[2];
        fm = xAxisTextPaint.getFontMetrics();
        float textWidth = xAxisTextPaint.measureText(text);
        float textHeight = fm.descent - fm.ascent;
        xy[0] = xCoordinateDistance - textWidth / 2;
        xy[1] = getHeight();
        return xy;
    }

    /**
     * 獲取x軸刻度文字坐標
     */
    private void getXAxisTextCoordinateList(){
        xAxisTextCoordinateList = new ArrayList<>();
        if(xAxisListNames != null) {
            xCoordinateDistance = getWidth() / (xAxisListNames.size() + 1);
            for (int i = 0; i < xAxisListNames.size(); i++) {
                float[] xtextCoordinate = getXtextCoordinate(xAxisListNames.get(i), xCoordinateDistance * (i + 1));
                xAxisTextCoordinateList.add(new Coordinate(xtextCoordinate[0], xtextCoordinate[1], xAxisListNames.get(i)));
            }
        }
    }

    /**
     * 獲取x軸線坐標
     */
    private void getXAxisCoordinateList(){
        xAxisCoordinateList = new ArrayList<>();
        if(xAxisListNames != null) {
            fm = xAxisTextPaint.getFontMetrics();
            float textHeight = fm.descent - fm.ascent;
            xCoordinateDistance = getWidth() / (xAxisListNames.size() + 1);
            for (int i = 0; i < xAxisListNames.size(); i++) {
                xAxisCoordinateList.add(new Coordinate(getX() + xCoordinateDistance * (i + 1)
                        , getHeight() - textHeight, xAxisListNames.get(i)));
            }
        }
    }
    /**
     * 獲取y軸刻度文字坐標
     */
    private void getYAxisTextCoordinateList(){
        yAxisTextCoordinateList = new ArrayList<>();
    }

    /**
     * 獲取y軸線坐標
     */
    private void getYAxisCoordinateList(){
        yAxisCoordinateList = new ArrayList<>();
    }

    private void getListAllNoAxisCoordinate(){
        listAllNoAxisCoordinate = new ArrayList<>();
        histogramShowFanWei = getHeight() - (fm.descent - fm.ascent) - defaultBetweenXAxisAndTextSpace;
        if(maxValue != null && xAxisListNames != null && xAxisCoordinateList != null){
            for(int  i = 0 ; i < xAxisListNames.size() ; i++) {
                if (histogramValue.get(xAxisListNames.get(i)) != null) {
                    listAllNoAxisCoordinate.add(new Coordinate(xAxisCoordinateList.get(i).getxCoordinate(),
                            (float) (xAxisCoordinateList.get(i).getyCoordinate() - (histogramShowFanWei * (histogramValue.get(xAxisListNames.get(i)) / maxValue))),
                            xAxisCoordinateList.get(i).getCoordinatename()));
                }
            }
            Collections.sort(listAllNoAxisCoordinate,new Coordinate());
        }
    }
}

調用方法:

 List list = new ArrayList<>();
        list.add("123");
        list.add("456");
        list.add("789");
        list.add("147");
        list.add("258");
        Map map = new HashMap<>();
        map.put(list.get(0),10d);
        map.put(list.get(1),15d);
        map.put(list.get(3),7d);
        ((HistogramNoScrollView)findViewById(R.id.test1)).setXAxisNames(list,true);
        ((HistogramNoScrollView)findViewById(R.id.test1)).setMaxValueAndAverageValue(20,10,true);
        ((HistogramNoScrollView)findViewById(R.id.test1)).setHistogramValue(map);
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved