自定义view-车型评分统计图

        先看效果,如下图:

         

        一。做一个效果之前,先分析由几种图形组成

        1.画横、纵坐标和刻度

        2.画柱形图

        3.手势的监听和页面打开时自动滑动

         

         二, 界面实现,分析各个组件和效果的实现

        1.画x,y轴和坐标

        画x轴,首先先计算view的总高度,减去上面的空白高度除于分数,就可以得出,x轴各个数字所在的位置,代码如下

   

 float textHeight = mHeight + paddingTop - bottomHeight;//横坐标高度
        vertialInterval = (textHeight - 200f) / 5;

        canvas.drawLine(startChart,0,startChart,textHeight,mLinePaint);
        canvas.drawLine(startChart,textHeight,mWidth,textHeight,mLinePaint);

    
 for (int i=0; i < vertileText.length; i++){

            float y =  (vertialInterval*i);

            mVertileTextpaint.getTextBounds(vertileText[i],0,vertileText[i].length(),mBound);
            canvas.drawText(vertileText[i],0,textHeight - y  + mBound.height() / 2,mVertileTextpaint);

            if (i > 0)
            canvas.drawLine(startChart,textHeight - y,startChart + 10,textHeight - y,mVertileTextpaint);
        }
      画Y轴,后面的柱形图的坐标用前面的坐标不断叠加,这里要控制滑动的区域,所以要剪裁canvas,要排除纵标左方的区域,这里裁剪使用

     

  canvas.clipRect(startChart + 10, 0, mWidth, getHeight(), Region.Op.REPLACE);
    前面表示裁剪的left,top,后面参数表示right,bottom坐标 ,接下来就可以画柱形图,和x轴刻度了

    

 float chartTempStart = startChart + xInterVal;

        float maxY = textHeight - 200f;
        for (int i=0; i < horText.length; i++){


            float height =  200f +  (10f - barDatas.get(i).getNum()) / 10f * maxY;

            String num = String.valueOf(barDatas.get(i).getNum());
            mVertileTextpaint.getTextBounds(num,0,num.length(),mBound);
            canvas.drawText(num,chartTempStart + mCurrentOrigin.x,height - mBound.height(),mVertileTextpaint);

            RectF rectF = new RectF();
            rectF.left = chartTempStart + mCurrentOrigin.x;
            rectF.top = height;
            rectF.right = chartTempStart + yellowBarWidth + mCurrentOrigin.x;
            rectF.bottom = textHeight - 3;
            canvas.drawRect(rectF,mChartPaint);

            chartTempStart += ( barWidth + startChart);
        }

        float grayBarStart = startChart + xInterVal ;
        for (int i=0; i < horText.length; i++){

            float height =  200f +  (10f - avgDatas.get(i).getNum()) / 10f * maxY;

            RectF rectF = new RectF();
            rectF.left = grayBarStart  + (yellowBarWidth + barInterval) + mCurrentOrigin.x;
            rectF.top = height;
            rectF.right = grayBarStart +  (yellowBarWidth + barInterval) + grayBarWidth + mCurrentOrigin.x;
            rectF.bottom = textHeight - 3;
            canvas.drawRect(rectF,mGrayPaint);

            grayBarStart += (barWidth + startChart );
        }


        float textTempStart = textStart;
        for (int i=0; i < horText.length; i++){

            mVertileTextpaint.getTextBounds(horText[i],0,horText[i].length(),mBound);
            canvas.drawText(horText[i],textTempStart - mBound.width()/2 + mCurrentOrigin.x,mHeight - bottomHeight + mBound.height() + 38f,mVertileTextpaint);

            textTempStart += (bottomHeight + startChart);
        }
    三。接下是手势的处理,这是这个view主要的学习点

     创建手势对象和监听器

     

 mGestureDetector = new GestureDetectorCompat(context, mGestureListener);
  private final GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {

        //手指按下
        @Override
        public boolean onDown(MotionEvent e) {
//            goToNearestBar();
            return true;
        }

        //有效的滑动
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {


            switch (mCurrentScrollDirection) {
                case NONE:
                    // 只允许在一个方向上滑动
                    if (Math.abs(distanceX) > Math.abs(distanceY)) {
                        if (distanceX > 0) {
                            mCurrentScrollDirection = Direction.LEFT;

                        } else {
                            mCurrentScrollDirection = RIGHT;
                        }
                    } else {
                        mCurrentScrollDirection = Direction.VERTICAL;
                    }
                    break;
                case LEFT:
                    // Change direction if there was enough change.
                    if (Math.abs(distanceX) > Math.abs(distanceY) && (distanceX < 0)) {
                        mCurrentScrollDirection = RIGHT;
                    }
                    break;
                case RIGHT:
                    // Change direction if there was enough change.
                    if (Math.abs(distanceX) > Math.abs(distanceY) && (distanceX > 0)) {
                        mCurrentScrollDirection = Direction.LEFT;
                    }
                    break;
            }


            // 重新计算滑动后的起点
            switch (mCurrentScrollDirection) {
                case LEFT:
                case RIGHT:
                    mCurrentOrigin.x -= distanceX * mXScrollingSpeed;
                    ViewCompat.postInvalidateOnAnimation(CommentBar.this);
                    break;
            }

            Log.e(" mCurrentOrigin.x " , mCurrentOrigin.x + "");
            return true;
        }

        //快速滑动
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {


            if ((mCurrentFlingDirection == Direction.LEFT && !mHorizontalFlingEnabled) ||
                    (mCurrentFlingDirection == RIGHT && !mHorizontalFlingEnabled)) {
                return true;
            }

            mCurrentFlingDirection = mCurrentScrollDirection;

            mScroller.forceFinished(true);

            switch (mCurrentFlingDirection) {
                case LEFT:
                case RIGHT:
                    mScroller.fling((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, (int) (velocityX * mXScrollingSpeed), 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
                    break;
                case VERTICAL:
                    break;
            }

            ViewCompat.postInvalidateOnAnimation(CommentBar.this);

            Log.e(" mCurrentOrigin.x2 " , mCurrentOrigin.x + "");
            return true;
        }


        //单击事件
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return super.onSingleTapConfirmed(e);
        }

        //长按
        @Override
        public void onLongPress(MotionEvent e) {
            super.onLongPress(e);
        }
    };

主要是处理快速滑动和滑动这两种手势,在快速移动的时候用到了OverScroer对象,这里的使用方法,在这里就不介绍了,这边主要是实现了他的一个回调方法,在回调方法处理相应的事件

  @Override
    public void computeScroll() {
        super.computeScroll();


        if (mScroller.isFinished()) {//当前滚动是否结束
            if (mCurrentFlingDirection != Direction.NONE) {
//                goToNearestBar();
            }
        } else {
            if (mCurrentFlingDirection != Direction.NONE && forceFinishScroll()) { //惯性滑动时保证最左边条目展示正确
//                goToNearestBar();
            } else if (mScroller.computeScrollOffset()) {//滑动是否结束 记录最新的滑动的点 惯性滑动处理
                mCurrentOrigin.y = mScroller.getCurrY();
                mCurrentOrigin.x = mScroller.getCurrX();
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }

    }

最后就是view首次的加载动画,这里是创建差值器,不断的去改变x轴的偏移量

   mValueAnimator = ValueAnimator.ofFloat(0,(getWidth()  + xInterVal - (horText.length * bottomHeight + (horText.length ) * vertialInterval + startChart)),0);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator)
            {

                Log.e(" valueAnimator ","" +   valueAnimator.getAnimatedValue());
                mCurrentOrigin.x = (float) valueAnimator.getAnimatedValue();

                invalidate();

            }
        });



        mValueAnimator.setDuration(2500);
        mValueAnimator.start();

到这里所有效果就分析完毕,完整代码如下,大家结合之后就更加清晰易懂了

package com.socks.scrollerdemo;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Build;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.animation.FastOutLinearInInterpolator;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.OverScroller;

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

import static com.socks.scrollerdemo.CommentBar.Direction.RIGHT;

/**
 * Created by ${charles}     on 2017/10/18.
 *
 * @desc ${TODO}
 */

public class CommentBar extends View
{
    private float xInterVal = 100f;
    private GestureDetectorCompat mGestureDetector;
    private int mHeight;
    private int mWidth;

    private float textStart;
    private int paddingTop = 20;

    private float startChart = 60f; //柱子开始的横坐标

    private float bottomHeight = 100f;//底部横坐标高度

    private float vertialInterval;//柱子之间的间隔

    private float barWidth = 100f;
    private float yellowBarWidth = 60;
    private float grayBarWidth = 20;
    private float barInterval = 10;

    private Paint mLinePaint;
    private Paint mVertileTextpaint;
    private Paint mChartPaint;
    private Paint mGrayPaint;

    private Rect mBound;
    private Context mContext;

    private String[] vertileText = {"0","2","4","6","8","10"};
    private String[] horText = {"外观","油耗","空间","舒适度","动力","操控","故障率","内饰","性价比","隔音率"};

    private boolean mHorizontalFlingEnabled = true;
    private OverScroller mScroller;
    //滑动速度
    private float mXScrollingSpeed = 1f;
    private int mMinimumFlingVelocity = 0;

    private int mScrollDuration = 250;
    public enum Direction {
        NONE, LEFT, RIGHT, VERTICAL
    }
    //正常滑动方向
    private Direction mCurrentScrollDirection = Direction.NONE;
    //快速滑动方向
    private Direction mCurrentFlingDirection = Direction.NONE;

    private PointF mCurrentOrigin = new PointF(0f, 0f);


    private ValueAnimator mValueAnimator;
    private final GestureDetector.SimpleOnGestureListener mGestureListener = new GestureDetector.SimpleOnGestureListener() {

        //手指按下
        @Override
        public boolean onDown(MotionEvent e) {
//            goToNearestBar();
            return true;
        }

        //有效的滑动
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {


            switch (mCurrentScrollDirection) {
                case NONE:
                    // 只允许在一个方向上滑动
                    if (Math.abs(distanceX) > Math.abs(distanceY)) {
                        if (distanceX > 0) {
                            mCurrentScrollDirection = Direction.LEFT;

                        } else {
                            mCurrentScrollDirection = RIGHT;
                        }
                    } else {
                        mCurrentScrollDirection = Direction.VERTICAL;
                    }
                    break;
                case LEFT:
                    // Change direction if there was enough change.
                    if (Math.abs(distanceX) > Math.abs(distanceY) && (distanceX < 0)) {
                        mCurrentScrollDirection = RIGHT;
                    }
                    break;
                case RIGHT:
                    // Change direction if there was enough change.
                    if (Math.abs(distanceX) > Math.abs(distanceY) && (distanceX > 0)) {
                        mCurrentScrollDirection = Direction.LEFT;
                    }
                    break;
            }


            // 重新计算滑动后的起点
            switch (mCurrentScrollDirection) {
                case LEFT:
                case RIGHT:
                    mCurrentOrigin.x -= distanceX * mXScrollingSpeed;
                    ViewCompat.postInvalidateOnAnimation(CommentBar.this);
                    break;
            }

            Log.e(" mCurrentOrigin.x " , mCurrentOrigin.x + "");
            return true;
        }

        //快速滑动
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {


            if ((mCurrentFlingDirection == Direction.LEFT && !mHorizontalFlingEnabled) ||
                    (mCurrentFlingDirection == RIGHT && !mHorizontalFlingEnabled)) {
                return true;
            }

            mCurrentFlingDirection = mCurrentScrollDirection;

            mScroller.forceFinished(true);

            switch (mCurrentFlingDirection) {
                case LEFT:
                case RIGHT:
                    mScroller.fling((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, (int) (velocityX * mXScrollingSpeed), 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0);
                    break;
                case VERTICAL:
                    break;
            }

            ViewCompat.postInvalidateOnAnimation(CommentBar.this);

            Log.e(" mCurrentOrigin.x2 " , mCurrentOrigin.x + "");
            return true;
        }


        //单击事件
        @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            return super.onSingleTapConfirmed(e);
        }

        //长按
        @Override
        public void onLongPress(MotionEvent e) {
            super.onLongPress(e);
        }
    };


    @Override
    public void computeScroll() {
        super.computeScroll();


        if (mScroller.isFinished()) {//当前滚动是否结束
            if (mCurrentFlingDirection != Direction.NONE) {
//                goToNearestBar();
            }
        } else {
            if (mCurrentFlingDirection != Direction.NONE && forceFinishScroll()) { //惯性滑动时保证最左边条目展示正确
//                goToNearestBar();
            } else if (mScroller.computeScrollOffset()) {//滑动是否结束 记录最新的滑动的点 惯性滑动处理
                mCurrentOrigin.y = mScroller.getCurrY();
                mCurrentOrigin.x = mScroller.getCurrX();
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }

    }

    /**
     * Check if scrolling should be stopped.
     *
     * @return true if scrolling should be stopped before reaching the end of animation.
     */
    private boolean forceFinishScroll() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            return mScroller.getCurrVelocity() <= mMinimumFlingVelocity;
        } else {
            return false;
        }
    }


    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        //将view的OnTouchEvent事件交给手势监听器处理
        boolean val = mGestureDetector.onTouchEvent(event);

        // 正常滑动结束后 处理最左边的条目
        if (event.getAction() == MotionEvent.ACTION_UP && mCurrentFlingDirection == Direction.NONE) {
            if (mCurrentScrollDirection == RIGHT || mCurrentScrollDirection == Direction.LEFT) {
//                goToNearestBar();
            }
            mCurrentScrollDirection = Direction.NONE;
        }
        return val;
    }

    public CommentBar(Context context)
    {
        super(context);
    }

    public CommentBar(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        mContext = context;
        //初始化手势

        initData();

        mGestureDetector = new GestureDetectorCompat(context, mGestureListener);

        // 解决长按屏幕后无法拖动的现象 但是 长按 用不了
        mGestureDetector.setIsLongpressEnabled(false);
        mScroller = new OverScroller(mContext, new FastOutLinearInInterpolator() );

        textStart = startChart  + xInterVal + (barWidth / 2f);
        mBound = new Rect();

        mLinePaint = new Paint();
        mLinePaint.setColor(Color.RED);
        mLinePaint.setAntiAlias(true);
        mLinePaint.setStyle(Paint.Style.FILL);
        mLinePaint.setStrokeWidth(3);

        mVertileTextpaint = new Paint();
        mVertileTextpaint.setAntiAlias(true);
        mVertileTextpaint.setColor(Color.RED);
        mVertileTextpaint.setTextSize(36);

        mChartPaint = new Paint();
        mChartPaint.setAntiAlias(true);
        mChartPaint.setColor(Color.YELLOW);
        mChartPaint.setStyle(Paint.Style.FILL);
        mLinePaint.setStrokeWidth(3);

        mGrayPaint = new Paint();
        mGrayPaint.setAntiAlias(true);
        mGrayPaint.setColor(Color.GRAY);
        mGrayPaint.setTextSize(36);



        mValueAnimator = ValueAnimator.ofFloat(0,(getWidth()  + xInterVal - (horText.length * bottomHeight + (horText.length ) * vertialInterval + startChart)),0);
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
        {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator)
            {

                Log.e(" valueAnimator ","" +   valueAnimator.getAnimatedValue());
                mCurrentOrigin.x = (float) valueAnimator.getAnimatedValue();

                invalidate();

            }
        });



        mValueAnimator.setDuration(2500);
        mValueAnimator.start();

        mValueAnimator.addListener(new Animator.AnimatorListener()
        {
            @Override
            public void onAnimationStart(Animator animator)
            {

            }

            @Override
            public void onAnimationEnd(Animator animator)
            {

            }

            @Override
            public void onAnimationCancel(Animator animator)
            {

            }

            @Override
            public void onAnimationRepeat(Animator animator)
            {



            }
        });
    }

    public CommentBar(Context context, AttributeSet attrs, int defStyleAttr)
    {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //宽度的模式
        int mWidthModle = MeasureSpec.getMode(widthMeasureSpec);
        //宽度大小
        int mWidthSize = MeasureSpec.getSize(widthMeasureSpec);

        int mHeightModle = MeasureSpec.getMode(heightMeasureSpec);
        int mHeightSize = MeasureSpec.getSize(heightMeasureSpec);
        //如果明确大小,直接设置大小
        if (mWidthModle == MeasureSpec.EXACTLY) {
            mWidth = mWidthSize;
        } else {
            //计算宽度,可以根据实际情况进行计算
            mWidth = (getPaddingLeft() + getPaddingRight());
            //如果为AT_MOST, 不允许超过默认宽度的大小
            if (mWidthModle == MeasureSpec.AT_MOST) {
                mWidth = Math.min(mWidth, mWidthSize);
            }
        }
        if (mHeightModle == MeasureSpec.EXACTLY) {
            mHeight = mHeightSize;
        } else {
            mHeight = (getPaddingTop() + getPaddingBottom());
            if (mHeightModle == MeasureSpec.AT_MOST) {
                mHeight = Math.min(mHeight, mHeightSize);
            }
        }
        //设置测量完成的宽高
        setMeasuredDimension(mWidth, mHeight);
    }

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

        //控制图表滑动左右边界
        if (mCurrentOrigin.x < getWidth() + xInterVal - (horText.length * bottomHeight + (horText.length ) * vertialInterval + startChart) )
            mCurrentOrigin.x = getWidth()  + xInterVal - (horText.length * bottomHeight + (horText.length ) * vertialInterval + startChart) ;

        Log.e(" ---- ",(horText.length * bottomHeight + (horText.length - 1) * vertialInterval + startChart) + "   getWidth() " +  getWidth());

        if (mCurrentOrigin.x > 0)
            mCurrentOrigin.x = 0;

        float textHeight = mHeight + paddingTop - bottomHeight;//横坐标高度
        vertialInterval = (textHeight - 200f) / 5;

        canvas.drawLine(startChart,0,startChart,textHeight,mLinePaint);
        canvas.drawLine(startChart,textHeight,mWidth,textHeight,mLinePaint);

        for (int i=0; i < vertileText.length; i++){

            float y =  (vertialInterval*i);

            mVertileTextpaint.getTextBounds(vertileText[i],0,vertileText[i].length(),mBound);
            canvas.drawText(vertileText[i],0,textHeight - y  + mBound.height() / 2,mVertileTextpaint);

            if (i > 0)
            canvas.drawLine(startChart,textHeight - y,startChart + 10,textHeight - y,mVertileTextpaint);
        }


        canvas.clipRect(startChart + 10, 0, mWidth, getHeight(), Region.Op.REPLACE);

        float chartTempStart = startChart + xInterVal;

        float maxY = textHeight - 200f;
        for (int i=0; i < horText.length; i++){


            float height =  200f +  (10f - barDatas.get(i).getNum()) / 10f * maxY;

            String num = String.valueOf(barDatas.get(i).getNum());
            mVertileTextpaint.getTextBounds(num,0,num.length(),mBound);
            canvas.drawText(num,chartTempStart + mCurrentOrigin.x,height - mBound.height(),mVertileTextpaint);

            RectF rectF = new RectF();
            rectF.left = chartTempStart + mCurrentOrigin.x;
            rectF.top = height;
            rectF.right = chartTempStart + yellowBarWidth + mCurrentOrigin.x;
            rectF.bottom = textHeight - 3;
            canvas.drawRect(rectF,mChartPaint);

            chartTempStart += ( barWidth + startChart);
        }

        float grayBarStart = startChart + xInterVal ;
        for (int i=0; i < horText.length; i++){

            float height =  200f +  (10f - avgDatas.get(i).getNum()) / 10f * maxY;

            RectF rectF = new RectF();
            rectF.left = grayBarStart  + (yellowBarWidth + barInterval) + mCurrentOrigin.x;
            rectF.top = height;
            rectF.right = grayBarStart +  (yellowBarWidth + barInterval) + grayBarWidth + mCurrentOrigin.x;
            rectF.bottom = textHeight - 3;
            canvas.drawRect(rectF,mGrayPaint);

            grayBarStart += (barWidth + startChart );
        }


        float textTempStart = textStart;
        for (int i=0; i < horText.length; i++){

            mVertileTextpaint.getTextBounds(horText[i],0,horText[i].length(),mBound);
            canvas.drawText(horText[i],textTempStart - mBound.width()/2 + mCurrentOrigin.x,mHeight - bottomHeight + mBound.height() + 38f,mVertileTextpaint);

            textTempStart += (bottomHeight + startChart);
        }



    }


    /**private void goToNearestBar() {

        //让最左边的条目 显示出来
        double leftBar = mCurrentOrigin.x / (bottomHeight + startChart);

        if (mCurrentFlingDirection != Direction.NONE) {
            // 跳到最近一个bar
            leftBar = Math.round(leftBar);
        } else if (mCurrentScrollDirection == Direction.LEFT) {
            // 跳到上一个bar
            leftBar = Math.floor(leftBar);
        } else if (mCurrentScrollDirection == RIGHT) {
            // 跳到下一个bar
            leftBar = Math.ceil(leftBar);
        } else {
            // 跳到最近一个bar
            leftBar = Math.round(leftBar);
        }

        int nearestOrigin = (int) (mCurrentOrigin.x - leftBar * (bottomHeight + startChart));

        if (nearestOrigin != 0) {
            // 停止当前动画
            mScroller.forceFinished(true);
            //开始滚动
            mScroller.startScroll((int) mCurrentOrigin.x, (int) mCurrentOrigin.y, -nearestOrigin, 0, (int) (Math.abs(nearestOrigin) / (bottomHeight + startChart) * mScrollDuration));
            ViewCompat.postInvalidateOnAnimation(CommentBar.this);
        }
        //重新设置滚动方向.
        mCurrentScrollDirection = mCurrentFlingDirection = Direction.NONE;

    }*/


    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        mWidth = getWidth();
        mHeight = getHeight() - paddingTop;
    }

    private List<BarData> barDatas = new ArrayList<>();
    private List<BarData> avgDatas = new ArrayList<>();
    private void initData(){
        barDatas.add(new BarData("外观",9.3f));
        barDatas.add(new BarData("油耗",8.1f));
        barDatas.add(new BarData("空间",9.5f));
        barDatas.add(new BarData("舒适度",8.8f));
        barDatas.add(new BarData("动力",8.5f));
        barDatas.add(new BarData("操控",8.6f));
        barDatas.add(new BarData("故障率",0.7f));
        barDatas.add(new BarData("内饰",8.6f));
        barDatas.add(new BarData("性价比",8.3f));
        barDatas.add(new BarData("隔音率",0.7f));

        avgDatas.add(new BarData("外观",9.1f));
        avgDatas.add(new BarData("油耗",7.7f));
        avgDatas.add(new BarData("空间",8.8f));
        avgDatas.add(new BarData("舒适度",8.6f));
        avgDatas.add(new BarData("动力",8.6f));
        avgDatas.add(new BarData("操控",8.6f));
        avgDatas.add(new BarData("故障率",2.6f));
        avgDatas.add(new BarData("内饰",8.5f));
        avgDatas.add(new BarData("性价比",8.2f));
        avgDatas.add(new BarData("隔音率",2.5f));
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值