折线图的绘制

来源:互联网 发布:那年呐服饰淘宝代理可信吗 编辑:程序博客网 时间:2024/04/30 12:17

最近在做股票相关的项目,避免不了折线图,在这里温习一下写法,都是很简单的东西。


先看一下效果图



然后贴代码:



public class FTenBrokenLineView extends View {    public int XPoint = DipUtil.dip2px(40);    //原点的X坐标    public int YPoint = DipUtil.dip2px(210);     //原点的Y坐标    public int XScale = 55;     //X的刻度长度    public int YScale = 40;     //Y的刻度长度    public int XLength = 300;        //X轴的长度    public int YLength = 210;        //Y轴的长度    public String[] XLabel;    //X的刻度    public String[] YLabel;    //Y的刻度    public String[] Data;      //数据    public String Title;    //显示的标题    private Context context;    private Paint axisPaint;// 轴线    private Paint dataPaint;// 数据线    private Paint yTextPaint;// 文字的笔    private Paint xTextPaint;    private Paint titlePaint; // Y轴顶部的提示    private Paint annulusPaint; // 数据圆环    private Paint paint;    private Path path;    Paint paint1;    private float radius = DipUtil.dip2px(4);// 数据圆环的半径    public FTenBrokenLineView(Context context, AttributeSet attrs) {        super(context, attrs);        this.context = context;        init();    }    public FTenBrokenLineView(Context context) {        super(context);        this.context = context;        init();    }    private void init() {        XLength = DataManager.getInstance(context).getDeviceWidth(context) - DipUtil.dip2px(70);// 这个是把屏幕的宽度减去两边的间距的和        YLength = DipUtil.dip2px(190);    }    /**     * 为折线图设置数据     *     * @param XLabels  x的刻度     * @param YLabels  y的刻度     * @param AllData  传入的数据     */    public void setInfo(String[] XLabels, String[] YLabels, String[] AllData) {        XLabel = XLabels;        YLabel = YLabels;        Data = AllData;        XScale = XLength / (XLabel.length - 1);        YScale = YLength / YLabel.length;// 因为Y轴方向上第0个点没有数据,所以要特殊处理        invalidate();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);//重写onDraw方法        initPaint();        canvas.drawLine(XPoint, YPoint, XPoint + XLength, YPoint, axisPaint);   //X轴        canvas.drawLine(XPoint, YPoint - YLength, XPoint, YPoint, axisPaint);   //画Y轴        for (int i = 1; i <= YLabel.length; i++) {            canvas.drawLine(XPoint, YPoint - i * YScale, XPoint + XLength, YPoint - i * YScale, axisPaint);  //画横着方向每一个刻度,长度是X轴的长度            int j = i - 1;// 因为Y轴方向上第0个点没有数据,这里特殊处理            canvas.drawText(YLabel[j], XPoint - DipUtil.dip2px(25), YPoint - i * YScale + DipUtil.dip2px(3), yTextPaint);  //文字        }        for (int i = 0; i < XLabel.length; i++) {            canvas.drawLine(XPoint + i * XScale, YPoint, XPoint + i * XScale, YPoint - YLength, axisPaint);  //画X轴方向刻度            if (i > 0 && YCoord(Data[i - 1]) != -999 && YCoord(Data[i]) != -999) {  //保证有效数据                paint1 = new Paint();                paint1.setAntiAlias(true);                paint1.setStyle(Paint.Style.FILL);                paint1.setColor(0x153ea3ff);// 这个颜色就蓝色不透明8%                path = new Path();// 以每一个间距绘制它的路径,然后填充颜色。                path.moveTo(XPoint + (i - 1) * XScale, YCoord(Data[i - 1]));                path.lineTo(XPoint + i * XScale, YCoord(Data[i]));                path.lineTo(XPoint + i * XScale, YPoint);                path.lineTo(XPoint + (i - 1) * XScale, YPoint);                path.close();                canvas.drawPath(path, paint1);// 这里是绘制阴影效果                canvas.drawLine(XPoint + (i - 1) * XScale, YCoord(Data[i - 1]), XPoint + i * XScale, YCoord(Data[i]), dataPaint);// 绘制数据线            }        }        // 循环X轴上的数据        for (int i = 0; i < XLabel.length; i++) {            // 这里是计算X轴上的标示长度,因为是分为两行,所以分割为2015 和 三季度,然后计算长度            String str1 = XLabel[i].substring(0, 4);            float strwid1 = xTextPaint.measureText(str1);            String str2 = XLabel[i].substring(4);            float strwid2 = xTextPaint.measureText(str2);            canvas.drawText(str1, (XPoint + i * XScale) - strwid1 / 2, YPoint + DipUtil.dip2px(15), xTextPaint);// 绘制X轴上的刻度数据,第一行2015            canvas.drawText(str2, (XPoint + i * XScale) - strwid2 / 2, YPoint + DipUtil.dip2px(30), xTextPaint);// 绘制X轴上的刻度数据,第二行三季度            str1 = null;            str2 = null;            canvas.drawCircle(XPoint + i * XScale, YCoord(Data[i]), radius, annulusPaint);// 绘制数据点,是一个圆环            paint = new Paint();            paint.setAntiAlias(true);            paint.setStyle(Paint.Style.FILL);            paint.setColor(context.getResources().getColor(R.color.background_gray));            canvas.drawCircle(XPoint + i * XScale, YCoord(Data[i]), radius * 2 / 3, paint);// 在圆环内部绘制一个圆,颜色为背景颜色        }    }    private void initPaint() {        axisPaint = new Paint();        axisPaint.setStyle(Paint.Style.STROKE);        axisPaint.setAntiAlias(true);        axisPaint.setStrokeWidth(DipUtil.dip2px(1));        axisPaint.setColor(context.getResources().getColor(R.color.line));        dataPaint = new Paint();        dataPaint.setStyle(Paint.Style.STROKE);        dataPaint.setAntiAlias(true);        dataPaint.setStrokeWidth(radius / 3);        dataPaint.setColor(context.getResources().getColor(R.color.blue));        annulusPaint = new Paint();        annulusPaint.setAntiAlias(true);        annulusPaint.setStrokeWidth(radius / 3);        annulusPaint.setColor(context.getResources().getColor(R.color.blue));        yTextPaint = new Paint();        yTextPaint.setAntiAlias(true);        yTextPaint.setColor(context.getResources().getColor(R.color.title_color));        yTextPaint.setTextSize(context.getResources().getDimension(R.dimen.text_size_12));        xTextPaint = new Paint();        xTextPaint.setColor(context.getResources().getColor(R.color.text_gray));        xTextPaint.setTextSize(context.getResources().getDimension(R.dimen.text_size_12));        xTextPaint.setAntiAlias(true);        titlePaint = new Paint();        titlePaint.setAntiAlias(true);        titlePaint.setColor(context.getResources().getColor(R.color.title_color));        titlePaint.setTextSize(context.getResources().getDimension(R.dimen.text_size));    }    /**     * 计算绘制时的Y坐标,无数据时返回-999     * @param y0     * @return     */    private float YCoord(String y0) {        double y;        double k;        try {            y = Double.parseDouble(y0);        } catch (Exception e) {            return -999;    //出错则返回-999        }        try {            k = (YLength - YScale) / (Double.parseDouble(YLabel[YLabel.length - 1]) - Double.parseDouble(YLabel[0]));            return (float) (((Double.parseDouble(YLabel[YLabel.length - 1]) - y) * k) + (YPoint - YLength));        } catch (Exception e) {        }        return 0;    }}






这就是一个自定义的view,使用的时候就在xml文件中使用


<com.....FTenBrokenLineView    android:id="@+id/flBrokenLine"    android:layout_width="match_parent"    android:layout_height="wrap_content" />
上面是xml文件中的
下面是在代码中添加数据:
private FTenBrokenLineView flBrokenLine;public String[] YLabel = {"0.5", "0.6", "0.7", "0.8", "0.9", "1.0", "1.1", "1.2"};    //X的刻度public String[] XLabel = {"2014三季度", "2014年报", "2015一季度", "2015中报", "2015三季度"};    //Y的刻度public String[] Data = {"0.9", "0.8", "1.1", "0.65", "0.92"};      //数据

flBrokenLine = ViewHolder.init(view, R.id.flBrokenLine);
flBrokenLine.setInfo(XLabel, YLabel, Data);

自定义的view代码写的很乱,因为中间写的时候会有覆盖问题,所以为了能显示出效果,就写的很随便了,也不是很通用。


diputil.dip2px方法就是px和dp转换的方法。


DataManager.getInstance(context).getDeviceWidth(context)这个方法就是获取屏幕的宽度。
YCoord() 方法是:根据传入的要显示的参数,把这些值转换为屏幕上Y轴的像素,然后绘制出数据点。转换的跪着就是计算y轴上每一个间距对应的像素的一个比率K,然后用最大值减去传入的参数得到的值乘,这个K,再加上上面空隙的间距,就是返回的值(这写的。。。。我自己都看不懂。。。。。。)反正就是一个数学的比率。

反正代码很简单,复习一下。。。。




0 0