安卓自定义控件之不可滑动柱状图

注释在代码中:


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.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;



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

/**
 * Created by wangliang on 0013/2016/9/13.
 * 思路:每传递一次坐标名称则更新一次视图,坐标的传递采用动态计算的方法,当更改坐标轴名称的时候,所有视图清空进行重绘,柱状图显示数量由所传递的徐州的名称决定
 */
public class HistogramNoScrollView 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 histogramPaint;//柱状图画笔
    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 HistogramNoScrollView(Context context) {
        super(context);
        initSetting(context,null);
    }

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

    public HistogramNoScrollView(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_2);
        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);

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

        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 HistogramNoScrollView setXAxisNames(List xAxisListNames,boolean whetherShowXAxis){
        this.xAxisListNames = xAxisListNames;
        this.whetherShowXAxis = whetherShowXAxis;
        return this;
    }

    /**
     * 设置y轴坐标文字
     * @param yAxisListNames
     * @return
     */
    public HistogramNoScrollView setYAxisNames(List yAxisListNames,boolean whetherShowYAxis){
        this.yAxisListNames = yAxisListNames;
        this.whetherShowYAxis = whetherShowYAxis;
        return this;
    }

    /**
     * 设置柱状图所要显示的最大值以及平均值
     * @param maxValue 最大值
     * @param averageValue 平均值
     * @param whetherShowAverageValue 是否显示平均值线
     * @return
     */
    public HistogramNoScrollView setMaxValueAndAverageValue(double maxValue,double averageValue,boolean whetherShowAverageValue){
        this.maxValue = maxValue;
        this.averageValue = averageValue;
        this.whetherShowAverageValue = whetherShowAverageValue;
        return this;
    }

    public HistogramNoScrollView setHistogramValue(Map histogramValue){
        this.histogramValue = histogramValue;
        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++){
            histogramPaint = new Paint();
            histogramPaint.setColor(listAllNoAxisCoordinate.get(i).getColor());
            canvas.drawRect(new Rect(Math.round(listAllNoAxisCoordinate.get(i).getxStartCoordinate())
                            ,Math.round(listAllNoAxisCoordinate.get(i).getyStartCoordinate())
                            ,Math.round(listAllNoAxisCoordinate.get(i).getxStopCoordinate())
                            ,Math.round(listAllNoAxisCoordinate.get(i).getyStopCoordinate()))
                    ,histogramPaint);
        }

    }

    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;
        LineCoordinate lineCoordinate;
        if(maxValue != null && xAxisListNames != null && xAxisCoordinateList != null){
            for(int  i = 0 ; i < xAxisListNames.size() ; i++){
                lineCoordinate = new LineCoordinate();
                lineCoordinate.setxStartCoordinate((float) (xAxisCoordinateList.get(i).getxCoordinate() - xCoordinateDistance * 0.45));
                lineCoordinate.setyStartCoordinate((float) (xAxisCoordinateList.get(i).getyCoordinate() -
                        histogramShowFanWei * (histogramValue.get(xAxisListNames.get(i)) / maxValue)));

                lineCoordinate.setxStopCoordinate((float) (xAxisCoordinateList.get(i).getxCoordinate() + xCoordinateDistance * 0.45));
                lineCoordinate.setyStopCoordinate((float) (xAxisCoordinateList.get(i).getyCoordinate()));
                lineCoordinate.setColor(Color.BLACK);
                listAllNoAxisCoordinate.add(lineCoordinate);
            }
        }
    }
}

调用方法:

   List<String> list = new ArrayList<>();
        list.add("123");
        list.add("456");
        list.add("789");
        list.add("147");
        list.add("258");
        Map<String,Double> 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);

坐标类参考:http://blog.csdn.net/cmwly/article/details/49951913

你可能感兴趣的:(自定义控件)