Android自定义圆角柱状图

本文实例为大家分享了Android自定义圆角柱状图的具体代码,供大家参考,具体内容如下

需求:

画一个圆角柱状图,显示12个月的数据,Y轴数据动态分割,如果是当前月,就画出当前月图片;点击柱状图变色,并显示虚线弹出当前月信息,滑动时弹框和虚线消失,柱状图刷新到最初。

1.HistogramRound

package com.broker.liming.widget;
 
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.TypedArray;
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.os.Build;
import android.support.annotation.Nullable;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
 
import com.broker.liming.R;
import com.broker.liming.bean.ChartData;
import com.broker.liming.utils.ArithUtil;
import com.broker.liming.utils.LogUtil2;
 
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
 
/**
 * @author chenhuirong
 * @Date 2018/12/10
 * @Description zhu
 */
 
public class HistogramRound extends ChartYdate {
    private int[] rect_color;
    private int rect_text_color;//矩形文字颜色
    private int rect_big_text_color;//矩形最大文字颜色
 
    private int rect_text_size;//矩形文字尺寸
 
    private getNumberListener listener;
    private int selectIndex = -1;
    private int yHeightSelect=0;
    private int leftSelector=0;
    private boolean isScrollow;//true 滑动 false点击
 
    private List<Integer> selectIndexRoles = new ArrayList<>();
    private List<Object> objects=new ArrayList<>();
 
    public HistogramRound(Context context) {
        super(context);
    }
 
    public HistogramRound(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initStyle(context,attrs);
    }
 
    public HistogramRound(Context context, AttributeSet attrs) {
        super(context, attrs);
        initStyle(context,attrs);
    }
    /*
     * 初始化样式属性
     */
    private void initStyle(Context context,AttributeSet attrs) {
        TypedArray types = context.obtainStyledAttributes(attrs, R.styleable.zqxchart_histogram);
        coordinates_color = types.getColor(R.styleable.zqxchart_histogram_hCoordinatesColor, Color.RED);
        rect_text_color = types.getColor(R.styleable.zqxchart_histogram_rectTextColor,Color.BLACK);
        rect_big_text_color=getResources().getColor(R.color.text_yellow);
        rect_text_size = types.getInteger(R.styleable.zqxchart_histogram_rectTextSize,28);
 
        x_text_color = types.getColor(R.styleable.zqxchart_histogram_hxTextColor,Color.BLACK);
        y_text_color = types.getColor(R.styleable.zqxchart_histogram_hyTextColor,Color.BLACK);
        x_text_size = types.getInteger(R.styleable.zqxchart_histogram_hxTextSize,30);
        y_text_size = types.getInteger(R.styleable.zqxchart_histogram_hyTextSize,28);
        xpCount = types.getInteger(R.styleable.zqxchart_histogram_hxPointCount,12);
        ypCount = types.getInteger(R.styleable.zqxchart_histogram_hyPointCount,12);
        rect_color = getResources().getIntArray(R.array.histogram_color);
        animType = types.getInteger(R.styleable.zqxchart_histogram_hanimType, Anim.ANIM_NONE);
        types.recycle();
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (xData!=null&&yData!=null){
            drawHistogramRound(canvas);
        }
 
    }
 
    /*
     * 画柱状图
     */
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void drawHistogramRound(Canvas canvas) {
        //如果没有设置x轴数据
        if (xData == null){
            throw new NullPointerException("x轴数据源不能为空!");
        }
        //如果没有设置y轴数据
        if (yData == null){
            throw new NullPointerException("y轴数据源不能为空!");
        }
        Paint histogramPaint = new Paint();
//        histogramPaint.setAntiAlias(true);
        histogramPaint.setStyle(Paint.Style.FILL);
        histogramPaint.setStrokeWidth((float) 4.0);
        histogramPaint.setStrokeCap(Paint.Cap.ROUND);
        //矩形上具体数据画笔
        Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//        tv_mudi.setTextSize(TypedValue.COMPLEX_UNIT_PX,getResources().getDimension(R.dimen.font_13));
//        textPaint.setTextSize(rect_text_size);
 
        Paint mPaintCircle = new Paint(Paint.ANTI_ALIAS_FLAG);
//        mPaintCircle.setStyle(Paint.Style.ANTI_ALIAS_FLAG);
//
        mPaintCircle.setStrokeWidth(2);
        mPaintCircle.setColor(Color.parseColor("#ff5932"));
        mPaintCircle.setPathEffect(new DashPathEffect(new float[]{4, 4}, 0));
        mPaintCircle.setAntiAlias(true);
        textPaint.setTextSize(getResources().getDimension(R.dimen.font_9));
        DecimalFormat formater = new DecimalFormat("0.000");
        for (int i=0; i<xpCount; i++){
            try {
                histogramPaint.setColor(rect_color == null
                        ? getResources().getColor(R.color.colorPrimary)
                        : rect_color[i]);
            }catch (ArrayIndexOutOfBoundsException e){
                histogramPaint.setColor(getResources().getColor(R.color.colorPrimary));
            }
            int alpha = anims[i].getAlpha();
            textPaint.setAlpha(alpha);
            histogramPaint.setAlpha(alpha);
            //计算执行动画当前y坐标
            float top = anims[i].getCurrentY();
            float left = oX+xCoordinates[i]-xSpacing/5;
            float right = oX+xCoordinates[i]+xSpacing/3;
            String a = formater.format(yData[i]);
            String ydata=a.substring(0,a.indexOf("."));
            int[] textSize = getTextSize(xData[i],textPaint);
            float textY = top - textSize[1]/2;
            LogUtil2.log("yMax-------"+yMax+"--ydata--"+ydata);
            if (Float.valueOf(ydata)>=yMax){
                textPaint.setColor(rect_big_text_color);
            }else {
                textPaint.setColor(rect_text_color);
            }
            LogUtil2.log("yData--------------->ydataY轴上的数据"+ydata);
            //画矩形上文字
//            canvas.drawText(ydata,left+20,textY,textPaint);
            //计算每条柱状图的宽度
//            double tempBarWidth = (((int) mXinterval) >> 1) / mCategoryList.size();
//            mBarPaint.setStrokeWidth((float) tempBarWidth);
            if (selectIndex==i){
                histogramPaint.setColor(ContextCompat.getColor(getContext(), R.color.name_ffa646));
                //draw x 坐标
                yHeightSelect= (int) top/*-getPaddingTop() */- getPaddingBottom()-xTextSurplus-x_text_size;
                yHeightSelect= (int) (/*(oY+75)-(*/top/*+getPaddingTop()/)*/);
                leftSelector= (int) (left+(right-left)/2);
//                canvas.drawLine(oX,top, oX,top-yHeight,mPaintCircle);
                Path path = new Path();
                path.moveTo(oX, oX+xWidth+40);
                path.lineTo(oX, oX+xWidth+40);
//                canvas.drawPath(path, mPaintCircle);
//                canvas.drawLine(oX,top,oX+xWidth+40,top,mPaintCircle);
                if (!isScrollow){
 
                listener.getNumber(i, (int) oY, leftSelector,yHeightSelect, (int) oX);
                }
                LogUtil2.log("setSelect--画:--getHeight"+getHeight()+"--left--"+left+"--height--"+yHeightSelect+"--top--"+top+"--oy--"+oY);
 
            }else {
                histogramPaint.setColor(ContextCompat.getColor(getContext(), R.color.color_1FA6FB));
 
            }
 
           //画每一个矩形
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){
                //画圆角柱只在5.0以上版本适用,以下版本会闪退
                canvas.drawRoundRect(left,top,right,oY,30,30,histogramPaint);
            }else {
                canvas.drawRect(left,top,right,oY,histogramPaint);
            }
 
            objects.add(histogramPaint);
        }
 
    }
 
    public void setPublicRefresh(){
        selectIndex=-1;
        invalidate();
        for (int i=0;i<objects.size();i++){
            Paint  paint= (Paint) objects.get(i);
            paint.setColor(ContextCompat.getColor(getContext(), R.color.color_1FA6FB));
            LogUtil2.log("柱子--"+paint);
        }
    }
//    public void isScrollow(boolean isScrollowt){
//        this.isScrollow=isScrollowt;
//    };
    /*
     * 设置数据
     */
    @Override
    public void setChartYdateData(ChartData chartData) {
        super.setChartYdateData(chartData);
        HistogramData histogramData = (HistogramData) chartData;
        this.rect_color = histogramData.getRectColor() != null ?
                histogramData.getRectColor() : this.rect_color;
        this.rect_text_size = getFinalValue(this.rect_text_size,histogramData.getRectTextSize());
        this.rect_text_color = getFinalValue(this.rect_text_color,histogramData.getRectTextColor());
    }
 
 
    @Override
    public void setOnLongClickListener(@Nullable OnLongClickListener l) {
        super.setOnLongClickListener(l);
        LogUtil2.log("onDraw--getX---弹框的长按事件:" + isScrollow);
    }
 
    @Override
    protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY);
        LogUtil2.log("onDraw--getX---弹框的滑动事件:" + isScrollow);
    }
 
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        LogUtil2.log("onDraw--getX---弹框的滑动改变事件:" + isScrollow);
    }
 
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int x =0;
        int y =0;
        int left = getPaddingLeft()+yTextSurplus;
        int top = 0;
        int right = xWidth/ 12+getPaddingLeft()+yTextSurplus;
        int bottom = yHeight;
//        int right = getWidth()/ 12;
//        int bottom = yHeight;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                x = (int) ev.getX();
                y = (int) ev.getY();
                LogUtil2.log("setSelect--666down--x" + x + "--left--" + y + "ev--x" + ev.getX() + "ev--y" + ev.getY());
 
//                if (isScrollow) {
                  /*  for (int i = 0; i < 12; i++) {
                        Rect rect = new Rect(left, top, right, bottom);
                        left += xWidth / 12;
                        right += xWidth / 12;
                        if (rect.contains(x, y)) {
                            if (listener != null) {
                                LogUtil2.log("setSelect--666down--x" + x + "--left--" + y + "ev--x" + ev.getX() + "ev--y" + ev.getY());
                                //抬起坐标减去放下坐标绝对值小于20代表点击,否则代表滑动
//                            if (Math.abs(ArithUtil.sub(ev.getX(), x)) <= 20 && Math.abs(ArithUtil.sub(ev.getY(), y)) <= 20) {
                                selectIndex = i;
                                selectIndexRoles.clear();
                                selectIndexRoles.add(selectIndex);
                                invalidate();
//                            }
                            }
                        }
                    }*/
//                }
                break;
            case MotionEvent.ACTION_MOVE:
                isScrollow=true;
                LogUtil2.log("setSelect--666Move--x" + x + "--left--" + y + "ev--x" + ev.getX() + "ev--y" + ev.getY());
 
                break;
            case MotionEvent.ACTION_UP:
                isScrollow=false;
                x = (int) ev.getX();
                y = (int) ev.getY();
                LogUtil2.log("setSelect--666UP--x" + x + "--left--" + y + "ev--x" + ev.getX() + "ev--y" + ev.getY());
                for (int i = 0; i < 12; i++) {
                    Rect rect = new Rect(left, top, right, bottom);
                    left += xWidth / 12;
                    right += xWidth / 12;
 
                    if (rect.contains(x, y)) {
                        if (listener != null) {
 
                            //抬起坐标减去放下坐标绝对值小于20代表点击,否则代表滑动
//                            if (Math.abs(ArithUtil.sub(ev.getX(), x)) <= 20 && Math.abs(ArithUtil.sub(ev.getY(), y)) <= 20) {
                            selectIndex = i;
                            selectIndexRoles.clear();
                            selectIndexRoles.add(selectIndex);
                            invalidate();
//                            }
                        }
                    }
                }
                break;
        }
        return true;
    }
 
 
    public void setListener(getNumberListener listener) {
        this.listener = listener;
    }
 
    public interface getNumberListener {
        void getNumber(int number, int x, int y,int HeightSelect,int ox);
    }
}

2.ChartYdate

package com.broker.liming.widget;
 
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
 
import com.broker.liming.R;
import com.broker.liming.bean.ChartData;
import com.broker.liming.utils.DensityUtil;
import com.broker.liming.utils.DoubleUtils;
import com.broker.liming.utils.LogUtil2;
 
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
 
/**
 * @author chenhuirong
 * @Date 2018/12/10
 * @Description  统计图
 *
 * */
public class ChartYdate extends View {
 
    protected final int xSurplus = 0;//x轴留余
    protected final int ySurplus = 20;//y轴留余
    protected final int xTextSurplus = 150;//x轴文字留余
    protected final int yTextSurplus = 100;//y轴文字留余
    protected float oX;//原点x
    protected float oY;//原点y
    protected int xWidth;//x轴宽度
    protected int yHeight;//y轴高度
    protected int xSpacing;//x轴坐标间距
    protected int ySpacing;//y轴坐标间距
    protected int xpCount = 7;//x轴坐标点数
    protected int ypCount = 7;//y轴坐标点数
    protected int[] xCoordinates;//x轴坐标点
    protected int[] yCoordinates;//y轴坐标点
    protected float yMax = 0f;//y轴最大刻度值
    protected String[] xData;//x轴数据
    protected float[] yData;//y轴数据
    protected int coordinates_color;//坐标系颜色
    protected int x_text_size;//x轴文字尺寸
    protected int y_text_size;//y轴文字尺寸
    protected int x_text_color;//x轴文字颜色
    protected int y_text_color;//y轴文字颜色
 
    protected boolean isAnim = true;
    protected Anim[] anims;//动画数组
    protected long interval = 100;//动画执行间隔
    protected int animType = -2;//动画
    private Paint mTableValuePaint;
//    private getNumberListener listener;
//    private int selectIndex = -1;
//    private List<Integer> selectIndexRoles = new ArrayList<>();
 
    public ChartYdate(Context context) {
        super(context);
    }
 
    public ChartYdate(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
 
    public ChartYdate(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
 
    @Override
    protected void onDraw(Canvas canvas) {
        LogUtil2.log("yData--------------->onDraw画布"+ypCount);
        initChartYdateProp();
        initCoordinateSystem(canvas);
        //开始动画
        if (isAnim){
            initAnims();
            post(animator);
            isAnim = false;
        }
    }
    /*
     * 初始化统计图属性
     */
    private void initChartYdateProp() {
        //x轴宽度
        xWidth = getWidth() - getPaddingLeft() - getPaddingRight() - yTextSurplus;
        //y轴宽度
        yHeight = getHeight() - getPaddingTop() - getPaddingBottom() - xTextSurplus;
        //x轴每个刻度的间距
        xSpacing = (xWidth-xSurplus-xWidth%xpCount)/xpCount;
        //y轴每个刻度的间距
        ySpacing = (yHeight-ySurplus-yHeight%ypCount)/ypCount;
        //坐标系原点x
        oX = getPaddingLeft()+yTextSurplus;
        //坐标系原点y  减70为了画出当月图片
        oY = getPaddingTop()+yHeight+xTextSurplus/2-70;
        //x轴各刻度点位置
        xCoordinates = new int[xpCount];
        //y轴各刻度点位置
        yCoordinates = new int[ypCount];
        //记录x轴刻度点位置  修改柱形图离坐标原点的距离
        for (int i=0; i<xpCount; i++){
            xCoordinates[i] = (i+1) * xSpacing- 30;
        }
        LogUtil2.log("yData--------------->ypCount记录y轴刻度点位置"+ypCount);
        //记录y轴刻度点位置
        for (int j=0; j<ypCount; j++){
            yCoordinates[j] = (j+1) * ySpacing;
            LogUtil2.log("yData--------------->henghe"+yCoordinates[j]);
        }
        LogUtil2.log("yData--------------->yCoordinates记录y轴刻度点位置"+yCoordinates.length);
    }
    /*
     * 初始化坐标系
     */
    private void initCoordinateSystem(Canvas canvas){
        Paint mainPaint = new Paint();
        mainPaint.setColor(coordinates_color);
        mainPaint.setAntiAlias(true);
        //draw x 坐标
//        canvas.drawLine(oX,oY, oX,oY-yHeight,mainPaint);
        //draw y 坐标
//        canvas.drawLine(oX,oY,oX+xWidth+40,oY,mainPaint);
        //刻度值画笔
        Paint textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(getResources().getColor(R.color.transparent));
        mTableValuePaint = new Paint();
        mTableValuePaint.setStrokeWidth(DensityUtil.dip2px(getContext(), 0.04f));
        mTableValuePaint.setStyle(Paint.Style.FILL);
        mTableValuePaint.setColor(ContextCompat.getColor(getContext(), R.color.text_666666));
        mTableValuePaint.setAntiAlias(true);
        mTableValuePaint.setTextSize(DensityUtil.dip2px(getContext(), 13));
        //draw x 刻度
        for (int i=0; i<xCoordinates.length; i++){
            //更改文字大小
//            textPaint.setTextSize(x_text_size);
            textPaint.setTextSize(getResources().getDimension(R.dimen.font_9));
            //更改文字颜色
            textPaint.setColor(x_text_color);
            //x轴刻度线
//            canvas.drawLine(oX+xCoordinates[i],oY,oX+xCoordinates[i],oY-5,mainPaint);
            //获取x轴文字宽高
            if (xData!=null&&xData.length>0){
                int[] textSize = getTextSize(xData[i],textPaint);
                //计算x轴文字x,y坐标偏移量
                int textX = textSize[0]/2;
                int textY = xTextSurplus/2 - textSize[1]/2;
                //画x轴文字
                canvas.drawText(xData[i],oX+xCoordinates[i]-textX,oY+textY,textPaint);
                String[] strNow = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString().split("-");
                Integer year = Integer.parseInt(strNow[0]);
                Integer month = Integer.parseInt(strNow[1]);
                //画当前月图片 + DensityUtil.dip2px(mContext, 6)
                if (month == Integer.parseInt(xData[i])) {
                    Bitmap arrow = BitmapFactory.decodeResource(getResources(), R.mipmap.current_month);
                    RectF rectF = new RectF((float) (oX+xCoordinates[i]-textX - DensityUtil.dip2px(getContext(), 10)),
                            (float) (oY+textY+60 - DensityUtil.dip2px(getContext(), 15)),
                            (float) (oX+xCoordinates[i]-textX + DensityUtil.dip2px(getContext(), 20)),
                            (float) (oY+textY+70 - DensityUtil.dip2px(getContext(), 3)));
                    canvas.drawBitmap(arrow, null, rectF, textPaint);
                }
            }
        }
        if(yMax == 0f){
            yMax = getYMax();
        }
        if(getYMax()==0){
            yMax=1.0f;
        }
 
        //draw y 刻度
        for (int j=0; j<ypCount; j++){
            //更改文字大小
            textPaint.setTextSize(y_text_size);
 
            //y轴刻度线
//            canvas.drawLine(oX,oY-yCoordinates[j],oX+5,oY-yCoordinates[j],mainPaint);
            //y轴刻度值
            int iYMax = (int)yMax;
            String datay;
            if (yMax - iYMax == 0){
                datay = (int)(yMax/ypCount*(j+1))+"";
            }else {
                datay = new DecimalFormat("0.000").format(yMax/ypCount*(j+1));
            }
            //平均分成4份
//            Double mMaxDiv = DoubleUtils.getLargerInterger(yMax, 7);
//            datay= String.valueOf((new BigDecimal((j + 1) * mMaxDiv).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue()));
 
 
            int att=(int) Math.floor(yMax);
            String mBigst=String.valueOf(att);
//            String mBigst=String.valueOf(yMax).substring(0, String.valueOf(yMax).indexOf("."));
            int maxLength=mBigst.length();
            int baseMax= att+1;
            if (maxLength>=2){
                baseMax= Integer.valueOf(mBigst.substring(0, 2))+1;
            }
            boolean isBreak=false;
            int margCount=0;
 
            String  ii="";//画y轴最大值
            String aa="";//间隔
            for (int i=baseMax;i<baseMax+100;i++){
                for (int a=100;a>0;a--){
                    if (i%a==0&&i/a<=6&&i/a>=4){
                        margCount=i/a;
                        ii= String.valueOf(i);
                        aa=String .valueOf(a);
                        isBreak=true;
                        break;
                    }
                }
                if (isBreak)
                    break;
            }
            for (int y=0;y<maxLength-2;y++){
                aa=aa+"0";
                ii=ii+"0";
            }
//            double mm=formatTosepara2(Double.valueOf(aa));
//            int mm+=Integer.parseInt(aa)*j;
            //String.valueOf(Integer.parseInt(aa)*(j+1))
            datay= formatTosepara2(Double.valueOf(Integer.parseInt(aa)*(j+1)));
//
            LogUtil2.log("ydate---+++"+datay+"---"+ii);
            //获取文字宽高
            int[] textSize = getTextSize(datay,textPaint);
            //计算画文字的坐标偏移量
            int textX = yTextSurplus/2 + textSize[0]/2;
            int textY = textSize[1]/2;
            //画y轴文字
            textPaint.setColor(y_text_color);
            if (j==0){
                canvas.drawText("0",oX-textX,oY,textPaint);
            }
            canvas.drawText(datay,oX-textX,oY-yCoordinates[j]+textY,textPaint);
        }
        LogUtil2.log("ydate---+++"+yData.toString());
 
    }
    public String formatTosepara2(double data) {
        int length = String.valueOf(data).split("\\.")[0].length();
        if (length < 4) {
            return String.format("%.2f", data);
        }
        DecimalFormat df = new DecimalFormat("##,###");
        return df.format(data);
    }
    /*
     * 准备动画
     */
    private void initAnims() {
        anims = new Anim[xpCount];
//        switch (animType){
//            case Anim.ANIM_TRANSLATE:
//                for (int i=0;i<xpCount;i++){
//                    float dataX = oX+xCoordinates[i];
//                    float dataY = oY-yData[i]/yMax*yCoordinates[yCoordinates.length-1];
//                    Anim anim = new Anim(dataX,dataY,dataX,oY);
//                    anim.setAnimation(new TranslateAnim());
//                    anim.setVelocity(interval*2);
//                    anims[i] = anim;
//                }
//                break;
//            case Anim.ANIM_ALPHA:
//                for (int i=0;i<xpCount;i++){
//                    float dataX = oX+xCoordinates[i];
//                    float dataY = oY-yData[i]/yMax*yCoordinates[yCoordinates.length-1];
//                    Anim anim = new Anim(dataX,dataY,dataX,dataY);
//                    anim.setAnimation(new AlphaAnim());
//                    anim.setAlpha(0);
//                    anim.setVelocity(interval * 3/2);
//                    anims[i] = anim;
//                }
//                break;
//            default:
//        for (int i=0;i<xpCount;i++){
//            float dataX = oX+xCoordinates[i];
//            float dataY = oY-yData[i]/yMax*yCoordinates[yCoordinates.length-1];
//            Anim anim = new Anim(dataX,dataY,dataX,dataY);
//            anim.setAnimation(new TranslateAnim());
//            anim.setVelocity(interval);
//            anims[i] = anim;
//        }
        for (int i=0;i<xpCount;i++){
            float dataX = oX+xCoordinates[i];
            LogUtil2.log("yData----------dataX"+oX+xCoordinates[i]);
            LogUtil2.log("yData----------yData"+yData.length);
            LogUtil2.log("yData----------xpCount"+xpCount);
            LogUtil2.log("yData----------yCoordinates"+yCoordinates.length);

            //平均分成4份
            Double mMaxDi = DoubleUtils.getLargerInterger(yMax, 7);
            //设置Y轴分值
            float total=0;
//            float total= (float) new BigDecimal((7) * mMaxDi).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            LogUtil2.log("最大值--"+yMax);
            int att=(int) Math.floor(yMax);
            String mBigst=String.valueOf(att);
//            String mBigst=String.valueOf((int) Math.floor(yMax));
            LogUtil2.log("最大值--"+yMax+"---"+mBigst);
//            String mBigst=String.valueOf(yMax).substring(0, String.valueOf(yMax).indexOf("."));
            int maxLength=mBigst.length();
            int baseMax= att+1;
            if (maxLength>=2){
                baseMax= Integer.valueOf(mBigst.substring(0, 2))+1;
            }
            boolean isBreak=false;
            String aa="";//间隔值
            String ii="";//y轴最大
            int margCount=0;//分多少份,动态设置
            for (int j=baseMax;j<baseMax+100;j++){
                for (int a=100;a>0;a--){
                    if (j%a==0&&j/a<=6&&j/a>=4){
                        margCount=j/a;
                        aa=String.valueOf(a);
                        ii=String.valueOf(j);
                        isBreak=true;
                        break;
                    }
                }
                if (isBreak)
                    break;
            }
 
            for (int y=0;y<maxLength-2;y++){
                aa=aa+"0";
                ii=ii+"0";
//                total= Float.parseFloat(String.valueOf(baseMax)+"0");
            }
            LogUtil2.log("total"+total);
            total= Float.parseFloat(ii);
            LogUtil2.log("aa--"+aa+"--total"+total);
            float dataY = oY-yData[i]/total*yCoordinates[yCoordinates.length-1];
            LogUtil2.log("yData----------dataY"+dataY);
            Anim anim = new Anim(dataX,dataY,dataX,dataY);
            anim.setAnimation(new TranslateAnim());
            anim.setVelocity(interval);
            anims[i] = anim;
            LogUtil2.log("yData----------anims"+anims);
        }
//                break;
//        }
    }
 
    /*
     * 获取y轴最大值
     */
    protected float getYMax(){
        if (yData == null || yData.length == 0){
            yData = new float[ypCount];
        }
        float max =0;
        for (int i=0; i<yData.length; i++){
            if (max < yData[i]){
                max = yData[i];
            }
        }
        return max;
    }
 
    /*
     * 获取文字宽高
     */
    protected int[] getTextSize(String str,Paint paint){
        //计算文字所在矩形,可以得到宽高
        Rect rect = new Rect();
        paint.getTextBounds(str, 0, str.length(), rect);
        int w = rect.width();
        int h = rect.height();
        return new int[]{w,h};
    }
    /*
     * 设置统计图属性
     */
    public void setChartYdateData(ChartData chartData) {
        if (chartData == null){
            throw new NullPointerException("折线图数据不能为空!");
        }
        this.xData = chartData.getXdata();
        this.yData = chartData.getYdata();
        this.xpCount = getFinalValue(this.xpCount,chartData.getXpCount());
        this.ypCount = getFinalValue(this.ypCount,chartData.getYpCount());
        this.coordinates_color = getFinalValue(this.coordinates_color,chartData.getCoordinatesColor());
        this.x_text_size = getFinalValue(this.x_text_size,chartData.getxTextSize());
        this.y_text_size = getFinalValue(this.y_text_size,chartData.getyTextSize());
        this.x_text_color = getFinalValue(this.x_text_color,chartData.getxTextColor());
        this.y_text_color = getFinalValue(this.y_text_color,chartData.getyTextColor());
        this.interval = getFinalValue((int) this.interval,chartData.getInterval());
//        this.animType = chartData.getAnimType() != -2 ? chartData.getAnimType()
//                : this.animType;
        this.yMax = chartData.getyMax() != 0f ? chartData.getyMax() : this.yMax;
    }
    /*
     * 设置正确属性值
     */
    protected int getFinalValue(int old,int news){
        old = news != 0 ? news : old;
        return old;
    }
    /*
     * 执行动画runnable
     */
    private Runnable animator = new Runnable() {
        @Override
        public void run() {
            LogUtil2.log("yData----------anims循环"+anims);
            LogUtil2.log("yData----------anims长多"+anims.length);
            for(Anim a : anims){
                LogUtil2.log("yData----------anims循环2"+a.isOver());
                if(!a.isOver()){
                    a.refresh();
                    postDelayed(this, interval);
                    invalidate();
                    return;
                }
            }
        }
    };
    /*
     * 更新数据并重绘
     */
    public void update(ChartData chartData){
        yMax = 0;
        setChartYdateData(chartData);
        isAnim = true;
        invalidate();
    }
 
  /*  @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        int left = 0;
        int top = 0;
        int right = xWidth/ 12;
        int bottom = yHeight;
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                for (int i = 0; i < 12; i++) {
                    Rect rect = new Rect(left, top, right, bottom);
                    left += xWidth / 12;
                    right += xWidth / 12;
                    if (rect.contains(x, y)) {
                        if (listener != null) {
                            listener.getNumber(i, x, y);
//                            isSelect=true;
//                            number = i;
                            selectIndex = i;
                            selectIndexRoles.clear();
                            selectIndexRoles.add(selectIndex);
                            invalidate();
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return true;
    }
    public void setListener(getNumberListener listener) {
        this.listener = listener;
    }
    public interface getNumberListener {
        void getNumber(int number, int x, int y);
    }*/
}

3.布局 activity_family_status嵌套在Scrollowview中

 <android.support.v4.widget.NestedScrollView
        android:id="@+id/scrollowview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fillViewport="true"
        android:layout_marginBottom="@dimen/lay_10"
        >
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            >
          
                <com.broker.liming.widget.HistogramRound
                    android:id="@+id/histogramchart"
                    android:layout_width="@dimen/lay_320"
                    android:layout_height="220dp"
                    android:layout_marginLeft="@dimen/lay_12"
                    chart:hCoordinatesColor="@color/text_999999"
                    chart:hxTextColor="@color/color_6a6a6a"
                    chart:hyTextColor="@color/color_1FA6FB"
                    />
            <LinearLayout/>
<android.support.v4.widget.NestedScrollView/>

4.运用FamilyStatusActivity

package com.broker.liming.activity;
 
import android.content.Context;
import android.content.Intent;
 
import android.support.annotation.RequiresApi;
import android.support.v4.widget.NestedScrollView;
import android.support.v7.widget.LinearLayoutManager;
import com.broker.liming.utils.ArithUtil;
import com.broker.liming.utils.BarUtils;
import com.broker.liming.utils.GsonUtils;
import com.broker.liming.utils.LogUtil2;
import com.broker.liming.utils.UIHelper;
import com.broker.liming.widget.HistogramData;
import com.broker.liming.widget.HistogramRound;
import com.broker.liming.widget.TitleBar;
 
import org.json.JSONException;
 
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
 
import butterknife.BindView;
 
import static com.sobot.chat.utils.ScreenUtils.dip2px;
import static com.sobot.chat.utils.ScreenUtils.px2dip;
 
/**
 * @Descpription:家庭现状
 * @Date: 2019/7/17.
 * @author:chenhuirong
 */
 
public class FamilyStatusActivity extends BaseActivity{
   
    @BindView(R.id.histogramchart)
    HistogramRound histogramChart;
 
    @BindView(R.id.scrollowview)
    NestedScrollView scrollowview;
    private FamilyStatusAdapter adapter;
    private FamilyStatusRateAdapter rateAdapter;
    private  HistogramData histogramData;
    //柱状图
//    @BindView(R.id.my_single_chart_view)
//    SingleView mMySingleChartView;
    @BindView(R.id.rl_single)
    RelativeLayout rlSingle;
    private List<Float> singlelist;
    private LinearLayout llSingle;

    private double mMax = 44;
    private List<FamilyPremiumArrayBean> listData = new ArrayList<>();
    private String monthBack;
 
 
    float[] ydata = new float[12];
    private String[] xdata= new String[12] ;
    private String[] xdataShow= new String[12] ;//仅为显示
    private boolean isScrollow=true;
    private boolean isFresh=false;
    int margCount=0;//共分多少份
    private LinearLayout line;
    private String name;
    public static void actionStart(Context context, String familyUuid,String names) {
        Intent intent = new Intent(context, FamilyStatusActivity.class);
        intent.putExtra("familyUuid", familyUuid);
        intent.putExtra("name",names);
        context.startActivity(intent);
    }
    @Override
    protected void initTitleBar() {
        TitleBar titleBar = (TitleBar) findViewById(R.id.title_bar);
        assert titleBar != null;
        /*titleBar.setLeftBackground(R.mipmap.back);*/
        titleBar.setLeftBackground(R.mipmap.order_back);
 
        titleBar.setTitle(name+"的家庭数据分析");
        titleBar.setTitleColor(R.color.text_000000);
 
        titleBar.setTitleBarBg(getResources().getColor(R.color.white));
        titleBar.setLeftClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                finish();
            }
        });
    }
 
    @Override
    protected int getContentView() {
        return R.layout.activity_family_status;
    }
    @Override
    protected boolean initBundle(Bundle bundle) {
       
    }
 
 
    @Override
    public void initData() {
        super.initData();
 
    }
 
    @Override
    protected void onResume() {
        super.onResume();
     
        getPieDate(familyUuid);
    }
 
    public void getHomeData() {
        try {
            UserBean query = UserBeanDao.query();
            requestServerPostForm(false, 100, HttpParams.getFamilyStatus(query, familyUuid));
 
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
 
    @Override
    public void initView() {
        xdata=new String[]{"1","2","3","4","5","6","7","8","9","10","11","12"};
        xdataShow=new String[]{"01","02","03","04","05","06","07","08","09","10","11","12"};
 
        initSingle();
 
        scrollowview.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                LogUtil2.log("onDraw--getX---isScrollow" +isScrollow);
                float x=0;
                float y=0;
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        x = event.getX();
                        y = event.getY();
 
                        LogUtil2.log("onDraw--getX---down" + event.getX() + "---" + y);
                        break;
                    case MotionEvent.ACTION_MOVE:
                        LogUtil2.log("onDraw--getX---move:" + event.getX() + "---");
//                        isFresh=true;
                        //在此刷新柱状图,防止多次刷新,多次重绘
                        if (isScrollow){
                            rlSingle.removeView(llSingle);
                            rlSingle.removeView(line);
                            histogramChart.setPublicRefresh();
//                            histogramChart.isScrollow(isFresh);
                            isScrollow=false;
                        }
                        break;
                    case MotionEvent.ACTION_CANCEL:
                    case MotionEvent.ACTION_UP:
//
                        //允许ScrollView截断点击事件,ScrollView可滑动
                        LogUtil2.log("onDraw--getX---up" + event.getX() + "mLastWownY:" + event.getY()+"x差值:"+Math.abs(ArithUtil.sub(event.getX(), x))+"--y差值:"+ Math.abs(ArithUtil.sub(event.getY(), y))  );
 
                        //抬起坐标减去放下坐标绝对值小于20代表点击,否则代表滑动
                       /* if (Math.abs(ArithUtil.sub(event.getX(), x)) <= 20 && Math.abs(ArithUtil.sub(event.getY(), y)) <= 20) {
//                            isScrollow=false;
                            isCheck=true;
                        }else {
//                            isScrollow=true;
                            isCheck=false;
                            histogramChart.isScrollow(false);
                            rlSingle.removeView(llSingle);
                            rlSingle.removeView(line);
                            if (isScrollow){
                                histogramChart.setPublicRefresh();
                                isScrollow=false;
                            }
                        }*/
                        break;
                }
 
                return false;
            }
        });
        changeStatusBarTextColor(true);
        BarUtils.setColorNoTranslucent(this, getResources().getColor(R.color.white));
    }
 
    /**
     * 弹出弹框
     */
 
    private void initSingle(){
        rlSingle = (RelativeLayout) findViewById(R.id.rl_single);
        singlelist = new ArrayList<>();
        rlSingle.removeView(llSingle);
        rlSingle.removeView(line);
 
        histogramChart.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                LogUtil2.log("onDraw--getX---弹框的长按事件:" + isScrollow);
                return false;
            }
        });
 
 
        histogramChart.setListener(new HistogramRound.getNumberListener() {
            @Override
            public void getNumber(int index, int height, int left,int selectorHeight,int ox) {
//                rlSingle.removeAllViews();
                LogUtil2.log("onDraw--getX---弹框:" + isScrollow);
                isScrollow=true;
//                if(!isFresh){
 
                    rlSingle.removeView(llSingle);
                    rlSingle.removeView(line);
                    line= (LinearLayout) LayoutInflater.from(FamilyStatusActivity.this).inflate(R.layout.layout_dash_line, null);
 
//                TextView view=new TextView(mContext);
//              view.setBackground(mContext.getResources().getDrawable(R.drawable.shape_dash_line));
                    RelativeLayout.LayoutParams viewParam=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);viewParam. topMargin=height-selectorHeight;
                    viewParam.topMargin=selectorHeight-5;
                    viewParam.leftMargin=dip2px(mContext,40);
                    viewParam.rightMargin=dip2px(mContext,30);
                    line.setLayoutParams(viewParam);
                    rlSingle.addView(line);
 
                    llSingle = (LinearLayout) LayoutInflater.from(FamilyStatusActivity.this).inflate(R.layout.layout_pro_expense, null);
                    LinearLayout ll_back=(LinearLayout)llSingle.findViewById(R.id.ll_back);
                    TextView tvMoney = (TextView) llSingle.findViewById(R.id.tv_month);
                    TextView tv_money=(TextView) llSingle.findViewById(R.id.tv_money);
                    if (singlelist!=null&&singlelist.size()>0){
                        tv_money.setText(formatTosepara2(singlelist.get(index))+"");
                    }else {
                        tv_money.setText("0");
                    }
                    String[] strNow = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString().split("-");
                    String year = strNow[0];
                    tvMoney.setText(year+"-"+xdataShow[index]);
                    RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
                            RelativeLayout.LayoutParams.WRAP_CONTENT);
 
                    LogUtil2.log("setSelect--callback--"+height+"--left---"+left+"---"+selectorHeight+"弹框高--"+dip2px(mContext,60)+"--差值--"+(height-(height-selectorHeight/*+px2dip(mContext,70)*/)-dip2px(mContext,60)));
                    LogUtil2.log("----宽-----+++"+params.width);
                    LogUtil2.log("setSelect--转换"+px2dip(mContext,height)+"--left---"+px2dip(mContext,left)+"---"+dip2px(mContext,selectorHeight));
                    int topmargin=0;
                    int leftmargin=0;
                    LogUtil2.log("setSelect--差距"+px2dip(mContext,height-selectorHeight));
                    if (index+1>6){
                        if (height-(height-selectorHeight)-dip2px(mContext,60)-dip2px(mContext,5)>0){
                            ll_back.setBackground(mContext.getResources().getDrawable(R.mipmap.right_bottom));
                            topmargin=height-(height-selectorHeight)-dip2px(mContext,60)-dip2px(mContext,5)/*+dip2px(mContext,70)*/;
                        }else {
                            topmargin= height-(height-selectorHeight)+dip2px(mContext,5)/*+dip2px(mContext,70)*/;
                            ll_back.setBackground(mContext.getResources().getDrawable(R.mipmap.right_top));
                        }
//
                        leftmargin=left-dip2px(mContext,150)+dip2px(mContext,40);
                    }else {
                        if (height-(height-selectorHeight)-dip2px(mContext,60)-dip2px(mContext,5)>0){
                            ll_back.setBackground(mContext.getResources().getDrawable(R.mipmap.left_bottom));
                            topmargin=height-(height-selectorHeight)-dip2px(mContext,60)-dip2px(mContext,5);
                        }else {
                            ll_back.setBackground(mContext.getResources().getDrawable(R.mipmap.left_top));
                            topmargin=height-(height-selectorHeight)+dip2px(mContext,5);
                        }
                        leftmargin=left;
                    }
                    params.leftMargin = leftmargin;
                    //相当于总布局的上方,需要减去家庭保费和保费距离
                    params.topMargin=topmargin/* selectorHeight+px2dip(mContext,64)*/;
//                LogUtil2.log("setSelect--callback--"+histogramChart.getHeight()+"---"+selectorHeight+"---left"+ params.topMargin);
//                if (x - 100 < 0) {
//                    params.leftMargin = 0;
//                } else if (x - 100 > relativeLayout.getWidth() - llSingle.getMeasuredWidth()) {
//                    params.leftMargin = relativeLayout.getWidth() - llSingle.getMeasuredWidth();
//                }
 
                    llSingle.setLayoutParams(params);
                    rlSingle.addView(llSingle);
//                }
            }
        });
    }
 
    private void changeStatusBarTextColor(boolean isBlack) {
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M) {
            if (isBlack) {
                getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);//设置状态栏黑色字体
            }else {
                getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);//恢复状态栏白色字体
            }
        }
    }
 
 
    private void setDate(FamilyYearCheakBean yearCheakBean) {
 
        if (yearCheakBean != null) {
            if (yearCheakBean.familyPremiumTotal != null && !yearCheakBean.familyPremiumTotal.equals("")) {
                tv_total_money.setText("合计年缴"+formatTosepara(Double.valueOf(String.valueOf(yearCheakBean.familyPremiumTotal))) + "元");
            }else {
                tv_total_money.setText("合计年缴0.00元");
 
            }
 
            String[] strNow = new SimpleDateFormat("yyyy-MM-dd").format(new Date()).toString().split("-");
            Integer year = Integer.parseInt(strNow[0]);
            Integer month = Integer.parseInt(strNow[1]);
            listData = yearCheakBean.familyPremiumArray;
            List<Double> list = new ArrayList<>();
            ArrayList<DotVo> temp = new ArrayList();
 
            for (int i = 0; i < listData.size(); i++) {
                FamilyPremiumArrayBean bean = listData.get(i);
                String yearback = bean.MONTH.substring(0, bean.MONTH.indexOf("-"));
                monthBack = bean.MONTH.substring(bean.MONTH.lastIndexOf("-") + 1);
//                mXdots[i] = yearback + "年\n" + monthBack + "月";
                list.add(Double.valueOf(bean.premium));
                double premium = 0;
                if (bean.premium != null && !bean.premium.equals("")) {
                    premium = Double.valueOf(bean.premium);
                    list.add(Double.valueOf(bean.premium));
                    singlelist.add(Float.valueOf(bean.premium));
                    ydata[i]=Float.valueOf(bean.premium);
 
                }
                DotVo tempDotVo = new DotVo(monthBack, premium);
                temp.add(tempDotVo);
 
            }
 
            Double[] toBeStored = list.toArray(new Double[list.size()]);
            mMax = checkMax(toBeStored);
 
        }
        //向下取整
        int att=(int) Math.floor(mMax);
        String mBigst=String.valueOf(att);
        int maxLength=mBigst.length();
        int baseMax= att+1;
        if (maxLength>=2){
            baseMax= Integer.valueOf(mBigst.substring(0, 2))+1;
        }
        boolean isBreak=false;
 
        for (int i=baseMax;i<baseMax+100;i++){
            for (int a=100;a>0;a--){
                if (i%a==0&&i/a<=6&&i/a>=4){
                    margCount=i/a;
                    isBreak=true;
                    break;
                }
            }
            if (isBreak)
                break;
        }
        for (int i=0;i<maxLength-2;i++){
 
        }
        LogUtil2.log("ydata---设置数据"+ydata.toString()+"--最大分数--"+margCount);
        histogramData = HistogramData.builder()
                .setXdata(xdata)
                .setYdata(ydata)
                .setYpCount(margCount)
//                .setAnimType(Anim.ANIM_ALPHA)
                .build();
        histogramChart.setChartYdateData(histogramData);
        histogramChart.update(histogramData);
 
    }
    public double checkMax(Double[] args) {
        double max = 0;
        for (int i = 0; i < args.length; i++) {
            if (args[i] > max) {
                max = args[i];
            }
        }
        return max;
    }
    @Override
    protected void onSuccess(String response, int id) {
        super.onSuccess(response, id);
 
        switch (id){
          
            case 200:
                yearCheakBean= GsonUtils.toObject(response,FamilyYearCheakBean.class);
            
                 setDate(yearCheakBean);
              
                break;
 
        }
 
    }
 
 
    /**
     * 将float类型的数据转换成以4位逗号隔开的字符串,并且保留两位有效数字
     */
    public String formatTosepara(double data) {
        int length = String.valueOf(data).split("\\.")[0].length();
        if (length < 4) {
            return String.format("%.2f", data);
        }
        DecimalFormat df = new DecimalFormat("#,####.00");
        return df.format(data);
    }
    public String formatTosepara2(double data) {
        int length = String.valueOf(data).split("\\.")[0].length();
        if (length < 4) {
            return String.format("%.2f", data);
        }
        DecimalFormat df = new DecimalFormat("##,###");
        return df.format(data);
    }
 
}

5.HistogramData

package com.broker.liming.widget;
 
import com.broker.liming.bean.ChartData;
 
/**
 * @author chenhuirong
 * @Date 2018/12/10
 * @Description 柱状图s
 */
 
public class HistogramData extends ChartData {
    private int[] rectColor;
    private int rectTextColor;
    private int rectTextSize;
 
    private HistogramData(Builder builder) {
        setXdata(builder.xdata);
        setYdata(builder.ydata);
        setXpCount(builder.xpCount);
        setYpCount(builder.ypCount);
        setCoordinatesColor(builder.coordinatesColor);
        setxTextSize(builder.xTextSize);
        setyTextSize(builder.yTextSize);
        setxTextColor(builder.xTextColor);
        setyTextColor(builder.yTextColor);
        setyMax(builder.yMax);
        setInterval(builder.interval);
        setAnimType(builder.animType);
        setRectColor(builder.rectColor);
        setRectTextColor(builder.rectTextColor);
        setRectTextSize(builder.rectTextSize);
    }
 
    public static Builder builder() {
        return new Builder();
    }
 
    public int[] getRectColor() {
        return rectColor;
    }
 
    public void setRectColor(int[] rectColor) {
        this.rectColor = rectColor;
    }
 
    public int getRectTextColor() {
        return rectTextColor;
    }
 
    public void setRectTextColor(int rectTextColor) {
        this.rectTextColor = rectTextColor;
    }
 
    public int getRectTextSize() {
        return rectTextSize;
    }
 
    public void setRectTextSize(int rectTextSize) {
        this.rectTextSize = rectTextSize;
    }
 
    public static final class Builder{
        private int rectTextSize;
        private int rectTextColor;
        private int[] rectColor;
        private int animType;
        private int interval;
        private int yMax;
        private int yTextColor;
        private int xTextColor;
        private int yTextSize;
        private int xTextSize;
        private int coordinatesColor;
        private int ypCount;
        private int xpCount;
        private float[] ydata;
        private String[] xdata;
 
        private Builder(){}
 
        public Builder setRectTextSize(int val) {
            rectTextSize = val;
            return this;
        }
 
        public Builder setRectTextColor(int val) {
            rectTextColor = val;
            return this;
        }
 
        public Builder setRectColor(int[] val) {
            rectColor = val;
            return this;
        }
 
        public Builder setAnimType(int val) {
            animType = val;
            return this;
        }
 
        public Builder setInterval(int val) {
            interval = val;
            return this;
        }
 
        public Builder setYMax(int val) {
            yMax = val;
            return this;
        }
 
        public Builder setYTextColor(int val) {
            yTextColor = val;
            return this;
        }
 
        public Builder setXTextColor(int val) {
            xTextColor = val;
            return this;
        }
 
        public Builder setYTextSize(int val) {
            yTextSize = val;
            return this;
        }
 
        public Builder setXTextSize(int val) {
            xTextSize = val;
            return this;
        }
 
        public Builder setCoordinatesColor(int val) {
            coordinatesColor = val;
            return this;
        }
 
        public Builder setYpCount(int val) {
            ypCount = val;
            return this;
        }
 
        public Builder setXpCount(int val) {
            xpCount = val;
            return this;
        }
 
        public Builder setYdata(float[] val) {
            ydata = val;
            return this;
        }
 
        public Builder setXdata(String[] val) {
            xdata = val;
            return this;
        }
 
        public HistogramData build() {
            return new HistogramData(this);
        }
    }
}

6.ChartData

package com.broker.liming.bean;
 
/**
 * 统计图父类数据类
 * Created by zqx on 16/6/27.
 */
public class ChartData {
    protected String[] xdata;
    protected float[] ydata;
    protected int xpCount;
    protected int ypCount;
    protected int coordinatesColor;
    protected int xTextSize;
    protected int yTextSize;
    protected int xTextColor;
    protected int yTextColor;
    protected int yMax;
    protected int interval;
    protected int animType = -2;
 
    protected ChartData(){}
 
    public String[] getXdata() {
        return xdata;
    }
 
    public void setXdata(String[] xdata) {
        this.xdata = xdata;
    }
 
    public float[] getYdata() {
        return ydata;
    }
 
    public void setYdata(float[] ydata) {
        this.ydata = ydata;
    }
 
    public int getXpCount() {
        return xpCount;
    }
 
    public void setXpCount(int xpCount) {
        this.xpCount = xpCount;
    }
 
    public int getYpCount() {
        return ypCount;
    }
 
    public void setYpCount(int ypCount) {
        this.ypCount = ypCount;
    }
 
    public int getCoordinatesColor() {
        return coordinatesColor;
    }
 
    public void setCoordinatesColor(int coordinatesColor) {
        this.coordinatesColor = coordinatesColor;
    }
 
    public int getxTextSize() {
        return xTextSize;
    }
 
    public void setxTextSize(int xTextSize) {
        this.xTextSize = xTextSize;
    }
 
    public int getyTextSize() {
        return yTextSize;
    }
 
    public void setyTextSize(int yTextSize) {
        this.yTextSize = yTextSize;
    }
 
    public int getxTextColor() {
        return xTextColor;
    }
 
    public void setxTextColor(int xTextColor) {
        this.xTextColor = xTextColor;
    }
 
    public int getyTextColor() {
        return yTextColor;
    }
 
    public void setyTextColor(int yTextColor) {
        this.yTextColor = yTextColor;
    }
 
    public int getyMax() {
        return yMax;
    }
 
    public void setyMax(int yMax) {
        this.yMax = yMax;
    }
 
    public int getInterval() {
        return interval;
    }
 
    public void setInterval(int interval) {
        this.interval = interval;
    }
 
    public int getAnimType() {
        return animType;
    }
 
    public void setAnimType(int animType) {
        this.animType = animType;
    }
}

注:参考demo时间太久我忘记了,网上可找到

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义带增长动画和点击弹窗提示效果的柱状图DEMO

    项目中最近用到各种图表,本来打算用第三方的,例如MPAndroid,这是一个十分强大的图表库,应用起来十分方便,但是最终发现和设计不太一样,没办法,只能自己写了.今天将写好的柱状图的demo贴在这,该柱状图可根据数据的功能有一下几点: 1. 根据数据的多少,动态的绘制柱状图柱子的条数: 2. 柱状图每条柱子的绘制都有动态的动画效果: 3. 每条柱子有点击事件,点击时弹出提示框,显示相关信息,规定时间后,弹窗自动消失. 好了,先上演示图: 下边贴出相关代码: 自定义柱状图类: package co

  • 100行Android代码轻松实现带动画柱状图

    为何要用带动画的柱状图呢? 最近,项目中遇到一个地方,要用到柱状图.所以这篇文章主要讲怎么搞一个柱子.100行代码,搞定柱状图! 圆角,头顶带数字.恩,这样用drawable也可以搞定.但是,这个柱子是有一个动画的,就是进入到界面的时候柱子不断的长高.这样的话,综合考虑还是用自定义View来做比较简便.效果如下图了: 完整Demo地址请到我的github下载地址: https://github.com/lixiaodaoaaa/ColumnAnimViewProject 关于尺寸 控件尺寸直接来

  • 详解Android自定义View--自定义柱状图

    绪论 转眼间,2016伴随着互联网寒冬和帝都的雾霾马上就过去了,不知道大家今年一整年过得怎么样?最近票圈被各个城市的雾霾刷屏,内心难免会动荡,庆幸自己早出来一年,也担忧着自己的未来的职业规划.无所谓了,既然选择了这个行业,我觉得大家就应该坚持下去,路是自己走的,及时再寒冬,只要你足够优秀,足够努力,相信你最后还是会找到自己满意的工作的.最后还要感谢今年博客之星大家对我的投票支持,非常感谢.不多说了,今天的主题是它–对,自定义View柱状图. 先来说说我最近在做什么吧?好久没有写博客了,最近手里有

  • Android自定义柱状图表的方法实例

    前言 本文将通过示例代码介绍如何自定义简单的直方图表,此图表并非常见的直方图表,而是可以分组的.此文不会过多涉及原理,比较简单,示例图片如下(gif图片没有制作好,有闪烁,请见谅): 对于该示例的代码实现,其实重点在于坐标轴.文字.直方图的位置控制,需要随滑动距离而动态更新.注意事项会在示例代码中标注.下面贴出示例代码 public class MultiGroupHistogramView extends View { private int width; private int height

  • Android实现简易的柱状图和曲线图表实例代码

    前言 之前有写过一个图表lib,但是开发的速度,大多很难跟上产品需求变化的脚步,所以修改了下原先的图表库,支持图表下面能整合table显示对应的类目,用曲线替换了折线,支持多曲线的显示,增加了显示的动画,增加了一些可定制的属性,支持水平柱状图和叠加柱状图,以及多曲线图和饼状图的显示,下面话不多说了,来一起看看详细的介绍吧. 1.效果图 2.各种图表的使用方式 1.饼状图 这个和原先的使用一样,只不过增加了一个动画,可以参看之前的文章,饼状图使用. 2.水平多柱状图 2.1 xml布局 <well

  • MPAndroidChart开源图表库的使用介绍之饼状图、折线图和柱状图

    MPAndroidChart开源图表库之饼状图 为大家介绍一款图标开源库MPAndroidChart,它不仅可以在Android设备上绘制各种统计图表,而且可以对图表进行拖动和缩放操作,用起来非常灵活.MPAndroidChart同样拥有常用的图表类型:线型图.饼图.柱状图和散点图. mpandroidchartlibrary.jar包下载地址: https://github.com/PhilJay/MPAndroidChart/releases 下面主要实现以下饼状图: 1.从上面的地址中下载

  • Android自定义view实现动态柱状图

    先看一下动态柱状图效果. 主要功能是可以自定义指定的字体,柱状图颜色,动态效果. 在自定义view public class Histogram extends View { int MAX = 100;//矩形显示的最大值 int corner = 0; //矩形的角度. 设置为0 则没有角度. double data = 0.0;//显示的数 double tempData = 0; //初始数据 int textPadding = 50; //字体与矩形图的距离 Paint mPaint;

  • Android自定义圆角柱状图

    本文实例为大家分享了Android自定义圆角柱状图的具体代码,供大家参考,具体内容如下 需求: 画一个圆角柱状图,显示12个月的数据,Y轴数据动态分割,如果是当前月,就画出当前月图片:点击柱状图变色,并显示虚线弹出当前月信息,滑动时弹框和虚线消失,柱状图刷新到最初. 1.HistogramRound package com.broker.liming.widget;   import android.annotation.TargetApi; import android.content.Con

  • Android自定义圆角ImageView

    废话不多说了,直接给大家贴代码了. java类如下: import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Color; import android.gra

  • android 自定义圆角button效果的实例代码(自定义view Demo)

    概述 在平时开发过程中经常会碰到需要使用圆角button的情况,一般也会包括很多其他小功能,比如要在里面添加img,设置不同的圆角大小等. 针对这样的场景,直接使用创建多个shape,定义多个xml文件也是可以实现的.但是如果使用非常频繁,那么直接自定义一个就会来的非常方便. 甚至在一些情况下,不是可以用shape定义的规则图形,比如需要用到贝塞尔曲线等. 如果全局需要这样风格的view,那么自定义一个View是非常必要的. 本文主要是个demo记录,如有需要的读者可以借鉴学习. Demo 主要

  • Android自定义圆角ImageView控件

    目前一些比较火的图片加载库虽然支持圆角加载,若你是接的别人作了一半的项目,刚好别人用的图片加载库刚好不支持圆角加载,那么这颗控件你值得拥有.(支持网络图片的加载) 1.创建CustomImageView 类在你的项目中(源码如下) import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.Bitmap.

  • Android 详解自定义圆角输入框和按钮的实现流程

    Android-自定义圆角输入框和按钮 我们的征程是星辰大海,而非人间烟尘 自定义圆角输入框 效果 1.在drawable/下面new Drawable Resources File 2.新建shape文件,在里面自定义xml文件样式 代码文件 <!-- res/drawable/button_shape_normal.xml --> <shape xmlns:android="http://schemas.android.com/apk/res/android" a

  • Android编程自定义圆角半透明Dialog的方法

    本文实例讲述了Android编程自定义圆角半透明Dialog的方法.分享给大家供大家参考,具体如下: 效果图如下: 只是在实例化的时候使用带样式的构造函数即可 new MyDialog(GameActivity.this, R.style.dialog); 在value文件夹中添加mydialogthemes.xml <?xml version="1.0″ encoding=" utf-8″?> <resources> <style name="

  • Android自定义view实现圆形、圆角和椭圆图片(BitmapShader图形渲染)

    一.前言 Android实现圆角矩形,圆形或者椭圆等图形,一般主要是个自定义View加上使用Xfermode实现的.实现圆角图片的方法其实不少,常见的就是利用Xfermode,Shader.本文直接继承ImageView,使用BitmapShader方法来实现圆形.圆角和椭圆的绘制,等大家看我本文的方法后,其他的类似形状也就都能举一反三来来画出来了. 二.效果图: 三.BitmapShader简介 BitmapShader是Shader的子类,可以通过Paint.setShader(Shader

  • Android自定义进度条的圆角横向进度条实例详解

    1.本文将向你介绍自定义进度条的写法,比较简单,但还是有些知识点是需要注意的: invalidate()方法 RectF方法的应用 onMeasure方法的应用 2.原理 画3层圆角矩形,底层为黑色,第二层为灰色,最上一层为进度条颜色,示例图如下: 3.效果图   实现圆角进度条还有很多其他方法,比如在Progress控件里填充圆角图片,通过拉伸图片来达到预想的效果,虽然听起来很简单,但实现起来还是有些麻烦的. 4.解说方法 (1)invalidate()方法 invalidate()是用来刷新

随机推荐