Android自定义简单折线图、饼图

Android自定义简单折线图、饼图_第1张图片Android自定义简单折线图、饼图_第2张图片Android自定义简单折线图、饼图_第3张图片

图一:LineChart;图二:YearLineChart;图三:PieChart

        记:不想导别人的库,只是简单的几个图,自己做的,很粗糙,但是可以根据需求自己改改。分享一下。

        改进空间:添加动画、对象复用、以及绘制文字时的坐标计算

        知识来源:小专栏(https://xiaozhuanlan.com/)作者GcsSloop的安卓自定义View教程,不高深但是很实                              用,第一次体验在网上花钱学知识。

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Region;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.List;

/**
 * Created by mystery_code on 2018/7/6 0006.
 * Description:
 * Update:
 */
public class LineChart extends View {
    public LineChart(Context context) {
        this(context, null);
    }

    public LineChart(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LineChart(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.LineChart);
        horizontalLine=ta.getDimensionPixelSize(R.styleable.LineChart_backgroundLineWidth,1);
        radius=ta.getDimensionPixelSize(R.styleable.LineChart_radius,10);
        textSize=ta.getDimensionPixelSize(R.styleable.LineChart_tSize,13);
        int textColor=ta.getColor(R.styleable.LineChart_tColor,getResources().getColor(R.color.colorAccent));
        int lineColor=ta.getColor(R.styleable.LineChart_backgroundLineColor,getResources().getColor(R.color.colorPrimary));
        limit=ta.getInt(R.styleable.LineChart_limitPoint,7);
        lineWidth=ta.getDimensionPixelSize(R.styleable.LineChart_lineWidth,1);
        if (null == paint) {
            paint = new Paint();
        }
        if (null == linePaint) {
            linePaint = new Paint();
        }

        paint.setColor(textColor);
//        paint.setColor(Color.parseColor("#00e1b3"));
        paint.setAntiAlias(true);
        paint.setTextSize(textSize);
        paint.setStrokeWidth(lineWidth);

        linePaint.setColor(lineColor);
//        linePaint.setColor(Color.parseColor("#999999"));
        linePaint.setAntiAlias(true);
        linePaint.setStrokeWidth(horizontalLine);
        ta.recycle();
    }

    private List list;
    //折线、圆、文字画笔
    private Paint paint;
    //背景线
    private Paint linePaint;
    //背景线粗细
    private float horizontalLine ;
    //圆点半径
    private float radius;
    //文字大小
    private float textSize ;
    //折线宽度
    private float lineWidth;

    //背景线粗细
//    private float horizontalLine = DensityUtil.dip2px(1f);
//    //圆点半径
//    private float radius = DensityUtil.dip2px(10f);
//    //文字大小
//    private float textSize = DensityUtil.sp2px(13f);
//    //折线宽度
//    private float lineWidth = DensityUtil.dip2px(2f);


    //文字间距
    private int dis;
    //单元距离
    private int unitDis = 0;
    //元素x坐标
    private int inX = 0;
    //折线图上部需要留的距离:文字边框+圆点半径
    private float top;
    //折线图下部需要留的距离:文字边框+圆点半径
    private float bottom;
    //可见原点个数
    private int limit;

    public void setData(List list) {
        this.list = list;
        if (null == p) {
            p = new Path[list.size()];
        }
        if (null == regions) {
            regions = new Region[list.size()];
        }
        invalidate();
    }

    private Path[] p;
    private float height;
    private float width;
    private float preX;
    private float preY;
    /**
     * 注意:mRegion这里使用来做圆点点击判断的集合,regions是所有点的集合
     */
    private Region[] regions;

    private Region mRegion;
    //剩余高度值
    private float retainH;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //计算最大值和最小值,从其差值来计算单位距离
        int max = find(list, 1);
        int min = find(list, 0);
        //初始化x坐标及top和bottom值
        Rect rectText = new Rect();
        paint.getTextBounds("2000", 0, 4, rectText);

        dis= (int) ((screenWidth-rectText.width())/(limit-1)-rectText.width());//根据原点个数限制计算点与点之间的距离

        top=rectText.height()+radius*1.5f;//1.5倍是为选中变化做准备
        bottom=rectText.height()+radius*1.5f;//同上
        //剩余高度值需要减去顶、底部预留距离以使折线及原点绘制时不会遮蔽文字
        retainH=height-top-bottom;
        //
        float h=height-bottom;
        //画背景灰线的宽度
        float stopline=screenWidth*(list.size()-1)/6;
        //画背景灰线
        canvas.drawLine(0, h / 5, stopline, h / 5, linePaint);
        canvas.drawLine(0, 2 * h / 5, stopline, 2 * h / 5, linePaint);
        canvas.drawLine(0, 3 * h / 5, stopline, 3 * h / 5, linePaint);
        canvas.drawLine(0, 4 * h / 5, stopline, 4 * h / 5, linePaint);
        canvas.drawLine(0, h, stopline, h, linePaint);
        /**
         * 以下在计算文字时的rect可复用,此处未做改变
         */
        if (null != list && list.size() > 0) {
            for (int i = 0; i < list.size(); i++) {
                String year = list.get(i).getYear().trim();
                int count = list.get(i).getCount();
                //年份画布计算
                Rect rect = new Rect();
                paint.getTextBounds(year, 0, year.length(), rect);
                if (i == 0) {
                    inX=rect.width()/2;
                    unitDis = rectText.width() + dis;
                }

                //数字计算
                String temp = count + "";
                Rect rect1 = new Rect();
                paint.getTextBounds(temp, 0, temp.length(), rect1);

                //画年份
                canvas.drawText(year, inX-rect.width()/2, height, paint);

                //画圆点
                float pointY = retainH / (max - min) * (count - min);
                if (null != p && null != regions) {
                    p[i] = new Path();
                    regions[i] = new Region();
                    if (list.get(i).isBig()) {
                        /**
                         * 说明:原点高度的计算:【剩余高度值-原点的高度(因为其方向与坐标轴相反)】+顶部留白的高度
                         */
                        p[i].addCircle(inX, retainH - pointY+top, radius * 1.5f, Path.Direction.CW);
                    } else
                        p[i].addCircle(inX, retainH - pointY+top, radius, Path.Direction.CW);
                    regions[i].setPath(p[i], mRegion);
                    //这里使用drawPath进行原点绘制而不是drawCircle的原因:需要对原点的点击事件做处理,参考onTouchEvent
                    canvas.drawPath(p[i], paint);
                }

                //画数字
                canvas.drawText(count + "", inX - rect1.width() / 2, (retainH - pointY+top) - radius - rect.height() / 2, paint);
                //画连线
                if (i != 0)
                    canvas.drawLine(preX, preY, inX, retainH - pointY+top, paint);
                preX = inX;
                preY = retainH - pointY+top;
                inX += rectText.width() + dis;//rect.width的值是变化的并不是不变的,但是rectText.w是不变的
            }
            scrollX = getScrollX();
            width = inX;
        }
    }



    /**
     * 获取最值
     * @param list 传入列表
     * @param type 1:最大值;0:最小值
     * @return
     */
    private int find(List list, int type) {
        int num = 0;
        for (int i = 0; i < list.size(); i++) {
            int count = list.get(i).getCount();
            if (0 == type) {
                num = num < count ? num : count;
            } else if (1 == type) {
                num = num > count ? num : count;
            }
        }
        return num;
    }

//    @Override
//    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//        int width=MeasureSpec.getSize(widthMeasureSpec);
//    }

    private int screenWidth;
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        this.height = h;
        mRegion = new Region(0, 0, (list.size()+10)*1000, (int)height);
        screenWidth=w;
    }

    //手指接触时的x,y坐标
    private float startX;
    private float startY;
    //中介数
    private float tempX;
    //是否可以点击(单次滑动不再视为点击)
    private boolean isClick;
    //每次滑动的距离
    private int scrollX;
    //原点变大变小的记录参数
    private int tempIndex;

    //控制滑动边沿
    private int count = 0;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                tempX = startX = event.getX();
                startY = event.getY();
                isClick = true;
                break;
            case MotionEvent.ACTION_MOVE:
                float currentX = event.getX();

                //右移
                if (currentX - tempX > unitDis) {
                    count--;
                    if (count < 0 || count > list.size() - limit) {
                        count++;
                        return true;
                    }
                    //右移取负值是坐标系本质存在的
                    scrollBy((int) -unitDis, 0);
                    scrollX = getScrollX();
                    tempX = currentX;
                    invalidate();
                    isClick = false;

                } else //左移
                    if (currentX - tempX < -unitDis) {
                    count++;
                    if (count < 0 || count > list.size() - limit) {
                        count--;
                        return true;
                    }
                    scrollBy((int) unitDis, 0);
                    scrollX = getScrollX();
                    tempX = currentX;
                    invalidate();
                    isClick = false;
                } else {

                }
                break;
            case MotionEvent.ACTION_UP:
                float endX = event.getX();
                float endY = event.getY();
                //手指抬起时,是否是点击事件(通过接口自定义点击事件)
                if (isClick && Math.abs(endX - startX) < unitDis && Math.abs(endY - startY) < unitDis) {
                    if (null != clickEvent) {
                        if (null == regions) {
                            return true;
                        }
                        for (int i = 0; i < regions.length; i++) {
                            //判断手指(endX + scrollX, endY)是否在原点的范围regions[i]内
                            if (regions[i].contains((int) (endX + scrollX), (int) endY)) {
                                //原点大小
                                if (tempIndex==i){
                                    list.get(i).setBig(!list.get(i).isBig());
                                }else {
                                    list.get(tempIndex).setBig(false);
                                    list.get(i).setBig(true);
                                }
                                tempIndex = i;
                                invalidate();
                                //事件处理
                                clickEvent.click(i);
                            }
                        }

                    }
                }
                break;
        }
        return true;
    }

    private ClickEvent clickEvent;

    public void setClickEvent(ClickEvent clickEvent) {
        this.clickEvent = clickEvent;
    }

    public interface ClickEvent {
        void click(int position);
    }

//    public class YearEntity {
//        private String year;
//        private int count;
//        private boolean big;
//
//        public String getYear() {
//            return year;
//        }
//
//        public void setYear(String year) {
//            this.year = year;
//        }
//
//        public int getCount() {
//            return count;
//        }
//
//        public void setCount(int count) {
//            this.count = count;
//        }
//
//        public YearEntity(String year, int count) {
//            this.year = year;
//            this.count = count;
//        }
//
//        public boolean isBig() {
//            return big;
//        }
//
//        public void setBig(boolean big) {
//            this.big = big;
//        }
//
//    }
}

自定义属性:values/attrs.xml(自建)



    
        
        
        
    

    
        
        
        
        
        
        
        
        
    

    
        
        
        
        
        
    
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.dataadt.qitongcha.utils.DensityUtil;
import com.dataadt.qitongcha.utils.EmptyUtil;
import com.dataadt.qitongcha.utils.LogUtil;

import java.util.List;


/**
 * Created by mystery_code on 2018/7/10 0010.
 * Description:
 * Update:
 */
public class YearLineChart extends View {
    private Line data;

    public YearLineChart(Context context) {
        this(context, null);
    }

    public YearLineChart(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public YearLineChart(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        paint = new Paint();
        paint.setColor(Color.parseColor("#333333"));
        paint.setTextSize(DensityUtil.sp2px(13f));
        paint.setAntiAlias(true);

        axisThick = DensityUtil.dip2px(2f);
        axisPaint = new Paint();
        axisPaint.setAntiAlias(true);
        axisPaint.setColor(Color.parseColor("#666666"));
        axisPaint.setStrokeWidth(axisThick);

        bgPaint = new Paint();
        bgPaint.setAntiAlias(true);
        bgPaint.setColor(Color.parseColor("#999999"));

        linePaint = new Paint();
        linePaint.setAntiAlias(true);
        linePaint.setStrokeWidth(DensityUtil.dip2px(2f));
        linePaint.setColor(Color.parseColor("#309dee"));

        radius = disY = disX = DensityUtil.dip2px(4f);
    }

    private int width;
    private int height;
    private Paint paint;
    private Paint axisPaint;
    private Paint bgPaint;
    private Paint linePaint;
    private float axisThick;
    private float radius;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        this.width = MeasureSpec.getSize(widthMeasureSpec);
        this.height = MeasureSpec.getSize(heightMeasureSpec);
    }

    private Rect rect;
    private int sH;
    private int sW;
    //字轴之间的距离
    private int disX;
    private int disY;
    //z的坐标集合
    private float[] axisX;
    private float[] axisY;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (null == data) return;
        String temp = "9999";
        if (rect == null) rect = new Rect();
        paint.getTextBounds(temp, 0, temp.length(), rect);
        sW = rect.width();
        sH = rect.height();
        List y = data.getY();
        List x = data.getX();
        List z = data.getZ();
        if (EmptyUtil.isList(x) || EmptyUtil.isList(y)) return;
        if (axisX == null) axisX = new float[z.size()];
        if (axisY == null) axisY = new float[z.size()];
        //Y轴剩余高度
        float retainH = height - sH * 3 - disY;

        //Y轴元素距离
        float unitY = retainH / (y.size() - 1);

        //画轴所用的高度计算
        float h = -unitY + 3 * sH / 2 + disY;
        int w = sW + disX;
        //X轴元素距离
        float unitX = (width - 2 * (w)) / x.size();

        //Y轴最大最小值
        int max = find(y, 1);
        int min = find(y, 0);


        int minX = find(x, 0);
        //单位Y坐标距离
        float unitZ = retainH / (max - min);

        //画单位
        String unit = "/件";
        canvas.drawText(unit, 0, unit.length(), sW, sH, paint);
        //画Y轴线
        canvas.drawLine(w, sH + disY, w, height - 3 * sH / 2 + axisThick / 2, axisPaint);
        //画X轴线
        canvas.drawLine(w, height - 3 * sH / 2, width, height - 3 * sH / 2, axisPaint);
        //画Y轴
        for (int i = 0; i < y.size(); i++) {
            h += unitY;
            String tempY = String.valueOf(y.get(i));
            paint.getTextBounds(tempY, 0, tempY.length(), rect);
            canvas.drawText(tempY, 0, tempY.length(), sW - rect.width(), h + sH / 2, paint);
            //横线线
            canvas.drawLine(w + disX, h, width, h, bgPaint);
//            axisY[i]=retainH-(z.get(i).getCount()-min)*unitZ+3*sH/2+disY;
        }
        //x轴坐标插值
        int dX = 0;
        //画X轴
        for (int i = 0; i < x.size(); i++) {
            w += unitX;
            if (i == 2) dX = x.get(i) - x.get(i - 1);
            String tempX = String.valueOf(x.get(i));
            paint.getTextBounds(tempX, 0, tempX.length(), rect);
            canvas.drawText(tempX, 0, tempX.length(), w - rect.width() / 2, height, paint);
            //竖线
            canvas.drawLine(w, 3 * sH / 2 + disY, w, height - 3 * sH / 2 - disY, bgPaint);
        }
        //x轴单元插值
        float uX = unitX / dX;
        //画点
        for (int i = 0; i < z.size(); i++) {
            YearD yearD = z.get(i);
            axisX[i] = (yearD.getYear() - minX) * uX + sW + disX + unitX;
            LogUtil.e(yearD.getYear() + ">" + minX + ">" + uX + ">" + sW + ">" + disX + ">" + unitX);
            axisY[i] = retainH - (z.get(i).getCount() - min) * unitZ + 3 * sH / 2 + disY;
            canvas.drawCircle(axisX[i], axisY[i], radius, linePaint);
            //画值
            String tempZ = String.valueOf(yearD.getCount());

            paint.getTextBounds(tempZ, 0, tempZ.length(), rect);

            canvas.drawText(tempZ, 0, tempZ.length(), axisX[i] - rect.width(), axisY[i] - radius, paint);
            //画折线
            if (i != 0) canvas.drawLine(axisX[i - 1], axisY[i - 1], axisX[i], axisY[i], linePaint);
        }

        canvas.save();
    }

    private int find(List inch, int type) {
        int num = 0;
        for (int i = 0; i < inch.size(); i++) {
            int count = inch.get(i);
            if (i == 0) num = count;
            if (0 == type) {
                num = num < count ? num : count;
            } else if (1 == type) {
                num = num > count ? num : count;
            }
        }
        return num;
    }

    public void setData(Line data) {
        this.data = data;
        invalidate();
    }
//    public class Line {
//        private List x;
//        private List y;
//        private List z;
//
//        public List getX() {
//            return x;
//        }
//
//        public void setX(List x) {
//            this.x = x;
//        }
//
//        public List getY() {
//            return y;
//        }
//
//        public void setY(List y) {
//            this.y = y;
//        }
//
//        public List getZ() {
//            return z;
//        }
//
//        public void setZ(List z) {
//            this.z = z;
//        }
//
//        public Line(List x, List y, List z) {
//            this.x = x;
//            this.y = y;
//            this.z = z;
//        }
//    }
//public class YearD {
//    private int year;
//    private int count;
//
//    public int getYear() {
//        return year;
//    }
//
//    public void setYear(int year) {
//        this.year = year;
//    }
//
//    public int getCount() {
//        return count;
//    }
//
//    public void setCount(int count) {
//        this.count = count;
//    }
//
//    public YearD(int year, int count) {
//        this.year = year;
//        this.count = count;
//    }
//}
}
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import java.util.List;

/**
 * Created by mystery_code on 2018/7/9 0009.
 * Description:
 * Update:
 */
public class PieChart extends View {
    //文字绘制所需画笔
    private Paint textPaint;
    //圆弧绘制画笔
    private Paint arcPaint;
    //中心白圆画笔
    private Paint innerPaint;
    //外圆半径
    private int outRadius;
    //内圆半径
    private int innerRadius;
    //距离
    private int dis;
    //传入数据集合数据
    private List list;
    //首尾留白
    private float top;

    public PieChart(Context context) {
        this(context, null);
    }

    public PieChart(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PieChart(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        textPaint = new Paint();
        textPaint.setAntiAlias(true);

        arcPaint = new Paint();
        arcPaint.setAntiAlias(true);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PieChart);
        outRadius=ta.getDimensionPixelSize(R.styleable.PieChart_outRadius,80);
        innerRadius=ta.getDimensionPixelSize(R.styleable.PieChart_innerRadius,50);
        top=ta.getDimensionPixelSize(R.styleable.PieChart_padding,10);
        int textSize=ta.getDimensionPixelSize(R.styleable.PieChart_pSize,13);
        textPaint.setTextSize(textSize);
        int lineThick = ta.getDimensionPixelSize(R.styleable.PieChart_lineThick, 1);
        textPaint.setStrokeWidth(lineThick);
        dis=innerRadius/2;
        ta.recycle();
    }


    //给定的宽度和高度
    private int width;
    private int height;

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        this.width=MeasureSpec.getSize(widthMeasureSpec);
        this.height=MeasureSpec.getSize(heightMeasureSpec);
    }

    private int[] centerX;
    private int[] centerY;

    //画圆的区域
    private RectF rectF ;
    //测量计算使用
    private Rect rect = new Rect();

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (null == list || list.size() == 0) return;
        //此处初始化的原因是控件在Activity的resume时会再次调用
        //初始化角度:即所绘制饼图从Y轴开始
        float currentAngle=-90;
        //用于右侧数量展示(即右侧占比的份数)
        int rightCount=0;

        int size = list.size();
        //**************整个坐标系平移了(因此坐标计算时需要考虑)************
        canvas.translate(width / 2, height / 2);
        if (centerX==null){
            centerX = new int[size];
            centerY = new int[size];
        }
        //圆饼图绘制区域
        if (null==rectF){
            rectF= new RectF(-outRadius, -outRadius, outRadius, outRadius);
        }
        //绘制圆弧
        for (int i = 0; i < size; i++) {
            PieEntity pieEntity = list.get(i);
            //饼图区块颜色
            int color = Color.parseColor("#" + pieEntity.getColor());
            arcPaint.setColor(color);
            //占比大小转化为角度度
            float sweepAngle=pieEntity.getPercent() * 360;
            //绘制圆弧
            canvas.drawArc(rectF, currentAngle, sweepAngle, true, arcPaint);
            //绘制圆弧的中点所在角度
            float degree = currentAngle + pieEntity.getPercent() * 180;


            //中点坐标计算
            double radian = Math.toRadians(degree);
            //Math函数的参数为弧度(弧度的cos值即为x轴坐标,sin值为Y轴坐标)
            centerX[i] = (int) (outRadius * Math.cos(radian));
            centerY[i] = (int) (outRadius * Math.sin(radian));
            //绘制右侧说明计数
            if (centerX[i] >0) rightCount++;
            //记录已绘制圆弧的角度
            currentAngle += sweepAngle;
        }
        //计算左侧占比份数
        int leftCount=size-rightCount;
        /**
         * 文字的绘制机制可根据需求进行改良
         */
        //计算绘制文字高度用以作为标准
        String temp="标准";
        textPaint.getTextBounds(temp, 0, temp.length(), rect);
        //字体高度
        int sH = rect.height();
        //绘制文字说明的剩余高度
        float retainH=width-2*top;
        //右侧文字之间的间距(不是文字的中轴线间距)
        float rightUnitDis=(retainH- sH *2*rightCount)/(rightCount-1);
        //左侧文字之间的间距(同上)
        float leftUnitDis=(retainH- sH *2*leftCount)/(leftCount-1);
        //文字绘制的左侧或右侧高度的初始值(为了不干扰到第一个文字的绘制,左右此处减去了i=0时的距离)
        float rightH=-width/2+top-rightUnitDis;
        //*左侧的文字绘制从底部开始
        float leftH=width/2-top+2*sH+leftUnitDis;

        //绘制说明
        for (int i=0;i0){
                //文字高度累计值
                rightH += (sH * 2+rightUnitDis);
                float endX=centerX[i]+dis;
                //绘制第一行文字
                canvas.drawText(name, 0, name.length(), endX, rightH - sH, textPaint);
                //绘制第二行文字(drawText不支持\n换行)
                canvas.drawText(percent, 0, percent.length(), endX, rightH, textPaint);
                //从弧线中点连接到文字中点(此处是两行文字所以stopY为rightH-sH)
                canvas.drawLine(centerX[i], centerY[i], endX , rightH - sH, textPaint);
            }else //左侧文字
                if (centerX[i]<=0){
                //同上
                leftH-=(2* sH+leftUnitDis);
                int length = name.length();
                int length1 = percent.length();
                if (length>length1) {
                    textPaint.getTextBounds(name, 0, name.length(), rect);
                }else {
                    textPaint.getTextBounds(percent, 0, percent.length(), rect);
                }
                float endX=centerX[i]-dis-rect.width();
                canvas.drawText(name, 0, name.length(), endX, leftH - sH, textPaint);
                canvas.drawText(percent, 0, percent.length(), endX, leftH, textPaint);
                canvas.drawLine(centerX[i], centerY[i], endX + rect.width() , leftH - sH, textPaint);
            }
        }

        innerPaint = arcPaint;
        //画中间的白色圆
        innerPaint.setColor(Color.parseColor("#FFFFFF"));
        canvas.drawCircle(0, 0, innerRadius, innerPaint);
        canvas.save();
    }

    public void setData(List list) {
        this.list = list;
        invalidate();
    }

//    出入数据参考
//    public class PieEntity {
//        private String name;
//        private float percent;
//        private String color;
//
//        public String getName() {
//            return name;
//        }
//
//        public void setName(String name) {
//            this.name = name;
//        }
//
//        public float getPercent() {
//            return percent;
//        }
//
//        public void setPercent(float percent) {
//            this.percent = percent;
//        }
//
//        public String getColor() {
//            return color;
//        }
//
//        public void setColor(String color) {
//            this.color = color;
//        }
//
//        public PieEntity(String name, float percent, String color) {
//            this.name = name;
//            this.percent = percent;
//            this.color = color;
//        }
//    }

}

DensityUtil类(YearLineChart中自定义属性未提取,使用的是转化工具为默认值)

import android.content.res.Resources;

/**
 * on 2016/8/13 15:00
 * 作用:px和dp互相转换工具
 */
public class DensityUtil {
    /**
     * 根据手机的分辨率从 dip 的单位 转成为 px(像素)
     */
    public static int dip2px(float dpValue) {
        final float scale = Resources.getSystem().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     */
    public static int px2dip(float pxValue) {
        final float scale = Resources.getSystem().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }
    /**
     * 将sp值转换为px值,保证文字大小不变
     */
    public static int sp2px(float spValue) {
        final float fontScale = Resources.getSystem().getDisplayMetrics().scaledDensity;
        return (int) (spValue * fontScale + 0.5f);
    }
}
实例所需xml:



    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        


        

        

        
    

所需代码:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        StatusBarUtil.transparent(this);
        setContentView(R.layout.activity_main_1);

        final List list=new ArrayList<>();
        for (int i=0;i<10;i++) {
            list.add(new YearEntity(String.valueOf(2000+i),new Random().nextInt(100)));
        }


//        final LineChart lc=findViewById(R.id.lc);
//        lc.setClickEvent(new ClickEvent() {
//            @Override
//            public void click(int position) {
//                Log.e(">>click>>",list.get(position).getYear());
//            }
//        });
//        lc.setData(list);

        LineChart lcs=findViewById(R.id.lcs);
        lcs.setData(list);
        lcs.setClickEvent(new LineChart.ClickEvent() {
            @Override
            public void click(int position) {
                Log.e(">>click>>",list.get(position).getYear());
            }
        });


        List pie=new ArrayList<>();
        float sum=1f;
        for (int i=0;i<10;i++) {
            pie.add(new PieEntity(0.1 + "", 0.1f, color(i)));
        }
        PieChart pc=findViewById(R.id.pc);
        pc.setData(pie);


        int[] x=new int[7];
        int[] y=new int[7];
        int[] z=new int[7];
        for (int i=x.length-1;i>=0;i--){
            y[i]=(7-i)*10;
            x[i]=2000+i;
            z[i]=i*10;
        }

        YearLineChart ylc = findViewById(R.id.ylc);
        ylc.setData(new Line(x,y,z));

    }
    private String color(int input){
        switch (input%3){
            case 0:return "022004";
            case 1:return "000086";
            case 2:return "ff2455";
        }
        return "ffffff";
    }
}

希望能帮到有需要的人。


你可能感兴趣的:(Android)