android之自定义view

自定义view

 

一:组合现有的view

   比较简单,暂时不举例子,以后补充

二:扩展已有的控件

  继承已有的控件,保留继承的父控件的特性,引入新特性

   举栗子说明:为九宫格增加分割线

  系统默认Gridview没有分割线,因此若想为Gridview引入分割线,则需要自己扩展系统属性,需要重写Gridview。

  

 

  看一下上面的图片,思路很简单,就是继承GridView增加属性,这里我们先了解一个方法dispatchDraw()

  ondraw() 和dispatchdraw()的区别

  绘制View本身的内容,通过调用View.onDraw(canvas)函数实现

  绘制自己的孩子通过dispatchDraw(canvas)实现

  View组件的绘制会调用draw(Canvas canvas)方法,draw过程中主要是先画Drawable背景,对 drawable调用setBounds()然后是draw(Canvas c)方法.有点注意的是背景drawable的实际大小会影响view组件的大小,drawable的实际大小通过getIntrinsicWidth()和getIntrinsicHeight()获取,当背景比较大时view组件大小等于背景drawable的大小

     画完背景后,draw过程会调用onDraw(Canvas canvas)方法,然后就是dispatchDraw(Canvas canvas)方法, dispatchDraw()主要是分发给子组件进行绘制,我们通常定制组件的时候重写的是onDraw()方法。值得注意的是ViewGroup容器组件的绘制,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用。因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法,或者自定制一个Drawable,重写它的draw(Canvas c)和 getIntrinsicWidth(), 

getIntrinsicHeight()方法,然后设为背景。

  

下面给出GridView源码:

 

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.widget.GridView;

import com.bingo.customer.R;


/**
 * ================================
 *
 * @author: zcb
 * @email: zhang-cb@foxmail.com
 * @time: 2018/5/31 17:48
 * @version: 1.0
 * @description: 自定义了GridView 增加了边线
 * =================================
 */
public class LineGridView extends GridView {


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

    public LineGridView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public LineGridView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        View localView1 = getChildAt(0);
        if (localView1 == null) {
            return;
        }
        int column = getWidth() / localView1.getWidth();
        int childCount = getChildCount();
        Paint localPaint;
        localPaint = new Paint();
        localPaint.setStyle(Paint.Style.STROKE);
        localPaint.setColor(getContext().getResources().getColor(R.color.colorAccent));
        localPaint.setStrokeWidth(2);
        for (int i = 0; i < childCount; i++) {
            View cellView = getChildAt(i);
            if ((i + 1) % column == 0) {
                //最右边的列 只画底线
                if (i < column) {
                    //第一行最右边的列 画一条上边横线
                    canvas.drawLine(cellView.getLeft(), cellView.getTop(), cellView.getRight(), cellView.getTop(), localPaint);
                }

                canvas.drawLine(cellView.getLeft(), cellView.getBottom(), cellView.getRight(), cellView.getBottom(), localPaint);
            } else if ((i + 1) > (childCount - (childCount % column))) {
                //
                canvas.drawLine(cellView.getRight(), cellView.getTop(), cellView.getRight(), cellView.getBottom(), localPaint);
            } else {
                if (i < column) {
                    //第一行 不含有最右边一列 画一条上边横线
                    canvas.drawLine(cellView.getLeft(), cellView.getTop(), cellView.getRight(), cellView.getTop(), localPaint);
                }
                canvas.drawLine(cellView.getRight(), cellView.getTop(), cellView.getRight(), cellView.getBottom(), localPaint);
                canvas.drawLine(cellView.getLeft(), cellView.getBottom(), cellView.getRight(), cellView.getBottom(), localPaint);
            }
        }
        if (childCount % column != 0) {
            for (int j = 0; j < (column - childCount % column); j++) {
                View lastView = getChildAt(childCount - 1);
                canvas.drawLine(lastView.getRight() + lastView.getWidth() * j,
                        lastView.getTop(),
                        lastView.getRight() + lastView.getWidth() * j,
                        lastView.getBottom(),
                        localPaint);
            }
        }
    }
}

 

 

 demo源码:https://github.com/zhangchunbin/Demo_Customer_view/blob/master/app/src/main/java/com/bingo/customer/view/gridview/LineGridView.java

 

三:重写View实现全新的控件

  基础知识:

    1,Canvas 画板

    2,Paint 画笔

    3,Color 颜色

      其中Color.parseColor(String str); 方法可以解析Alpha颜色和普通的颜色。

    4,Bitmap 位图

 

  首先,我们需要明白这是一种完全的自定义控件的形式,只有当我们遇到原生控件无法满足的时候才会想要这种办法。

  自定义控件分为以下几个步骤:

  Ⅰ、在OnMeasure()方法中,测量自定义控件的大小,使自定义控件能够自适应布局各种各样的需求。

  Ⅱ、在OnDraw()方法中,利用哼哈二将(Canvas与Paint)来绘制要显示的内容。

  Ⅲ、在OnLayout()方法中来确定控件显示位置。

  Ⅳ、在OnTouchEvent()方法处理控件的触摸事件。

  对应的思维导图如下:

  

 

  下面将举个我遇到的栗子view:

   

  看下上面这个View的图,用于显示芝麻分认证以后显示芝麻分等级的view。这是个简单的例子,简单分析一下,一共有三行,

  第一行显示等级汉字(较差、中等、良好、优秀、极好),其中极好这个等级是有背景,并且背景颜色是根据当前分数决定的。

  第二行是5个等级不同颜色的view。

  第三行是显示不同的分数开始和结束的数字。

  分析结束,我们自定义view要把这个分成三行分开来,一行一行画。

  第一步是onMeasure()方法,测量view将使用的宽高。

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int height = getPaddingTop() + getPaddingBottom() + lineWidth + padding_img + 20 + textHeight + padding_text;
        Log.i(Tag, "height:" + height);
        Log.i(Tag, "getPaddingBottom():" + getPaddingBottom() + ",getPaddingTop():" + getPaddingTop() + "padding_img:" + padding_img + "lineWidth" + lineWidth);
        setMeasuredDimension(getMeasuredWidth(), height);
    }

  

  第二步是onDraw()方法:

  

 

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画第一行 5个等级的文字
        Rect rect = getTextWH(currentDialvalue + "", textSize);
        //修正边界
        Log.i(Tag, "textgetPaddingTop:" + getPaddingTop());
        int text_ph = getPaddingTop() + rect.height() - 7;

        if (currentDialvalue >= 350 && currentDialvalue < 550) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.jiaocha_start));
            draw5Characters(canvas, 1,  text_ph);
        } else if (currentDialvalue >= 550 && currentDialvalue < 600) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.zhongdeng_start));
            draw5Characters(canvas, 2,  text_ph);
        } else if (currentDialvalue >= 600 && currentDialvalue < 650) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.lianghao_start));
            draw5Characters(canvas, 3, text_ph);
        } else if (currentDialvalue >= 650 && currentDialvalue < 700) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.youxiu_start));
            draw5Characters(canvas, 4,  text_ph);
        } else if (currentDialvalue >= 700 && currentDialvalue < 950) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.jihao_start));
            draw5Characters(canvas, 5, text_ph);
        }

        //画第二行不同颜色矩形
        int bgline_ph = lineWidth / 2 + 1 + getPaddingTop() + textHeight + padding_text;
        draw5Line(canvas, bgline_ph);
        //画第三行等级数字
        drawLevelNum(canvas);
    }

  

   这其中有个细节必须要注意:画每一个汉字的时候,必须先确定这个字当前需不需要背景,如果需要背景则要画上背景,如果不需要背景则只需要画汉字即可,画汉字代码如下:

 

 /**
     * 画第一行5个等级词语{较差,中等,良好,优秀,极好}
     * @param canvas 画布
     * @param index 第一个需要背景
     * @param text_ph 高
     */
    public void draw5Characters(Canvas canvas, int index, int text_ph) {

        final float stepWidth = (getMeasuredWidth() - getPaddingRight() - cap) / 5;
        final float offsetWidth = getPaddingLeft() + stepWidth / 3;

        for (int i = 1; i <= 5; i++) {
            if (i == index) {
                // 背景矩形
                float left = stepWidth * (i - 1) + offsetWidth - 15;
                float top = getPaddingTop() - 20;
                float right = left + getTextWH("测试", textSize).width() + 30;
                float bottom = text_ph + 15;
                RectF oval3 = new RectF(left, top, right, bottom);
                canvas.drawRoundRect(oval3, 6, 6, recPaint);

                /**
                 * 三角形
                 *  *******
                 *   *****
                 *    ***
                 *     *
                 */
                Path path = new Path();
                path.moveTo(left, getPaddingTop());// 三角形的起顶点
                path.lineTo(right, getPaddingTop());//三角形右边的顶点
                path.lineTo((left + right) / 2, bottom + 10);  //三角形下面的顶点
                path.close(); // 使这些点构成封闭的多边形
                canvas.drawPath(path, recPaint);

                paint_text_value.setColor(Color.WHITE);
                canvas.drawText(paintString[i - 1], stepWidth * (i - 1) + offsetWidth, text_ph, paint_text_value);

            } else {
                canvas.drawText(paintString[i - 1], stepWidth * (i - 1) + offsetWidth, text_ph, hanziPaint);
            }
        }
    }

   

  第二行不同颜色的矩形图笔比较简单,但是需要注意的细节是,背景颜色是渐变的,不是一层不变的颜色,具体代码如下:

  其中画渐变颜色的方法也很简单,使用系统自带的类LinearGradient,画渐变背景颜色代码如下:

linearGradient = new LinearGradient(startXPoint, 0, stopXPoint, 0, new int[]{lineColors.get(i - 1).startColor, lineColors.get(i - 1).stopColor}, null, LinearGradient.TileMode.CLAMP);
            paint_bg.setShader(linearGradient);

 

  下面就是画第二行矩形的全部代码:

    /**
     * 画第二行5条等级颜色渐变线
     */
    public void draw5Line(Canvas canvas, int bgline_ph) {
        float startXPoint;
        float stopXPoint;
        float tempXPoint;

        for (int i = 1; i <= 5; i++) {
            startXPoint = (getMeasuredWidth() - getPaddingRight() - cap) / 5 * (i - 1) + getPaddingLeft();
            stopXPoint = (getMeasuredWidth() - getPaddingRight() - cap) / 5 * i + getPaddingLeft();
            if (i % 2 == 0) {  //第偶数次循环,交换起始点
                tempXPoint = startXPoint;
                startXPoint = stopXPoint;
                stopXPoint = tempXPoint;
            }

            linearGradient = new LinearGradient(startXPoint, 0, stopXPoint, 0, new int[]{lineColors.get(i - 1).startColor, lineColors.get(i - 1).stopColor}, null, LinearGradient.TileMode.CLAMP);
            paint_bg.setShader(linearGradient);
            canvas.drawLine(startXPoint, bgline_ph, stopXPoint, bgline_ph, paint_bg);
        }
    }

 

 

到了画第三行数字的时候了,也是比较简单的,难点在于位置的定位,刚开始的时候我怎么都找不到位置,多次修改尝试之后才最终确定,不多说了,直接上代码吧:

    /**
     * 画第三行的等级数字{350,550,600,650,70,950}
     *
     * @param canvas
     */
    public void drawLevelNum(Canvas canvas) {
        Paint mPaint = new Paint();
        mPaint.setStrokeWidth(3);
        mPaint.setTextSize(25);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.GRAY);
        mPaint.setTextAlign(Paint.Align.CENTER);

        int img_postion_h = lineWidth + padding_img + getPaddingTop() + textHeight + padding_text;
        Log.i(Tag, "img_postion_h:" + img_postion_h);
        float pre = allLength / 5;
        float offsetw = 20 / 3 * -1;
        for (int i = 0; i < level_num.length; i++) {
            if (i == level_num.length - 1) {
                canvas.drawText(level_num[i] + "", allLength + getPaddingLeft() + cap, img_postion_h + 25, mPaint);
            } else {
                if (i == 0) {
                    canvas.drawText(level_num[i] + "", i * pre + getPaddingLeft() + cap, img_postion_h + 25, mPaint);
                } else {
                    canvas.drawText(level_num[i] + "", i * pre + offsetw + getPaddingLeft() + cap + 20, img_postion_h + 25, mPaint);
                }
            }
        }
    }

 

 

  至此,三行都画完了之后吗,这个view也就成型了,总的来说不难,但是刚开始的时候会找不到入口点,还是需要多练习,本人才疏学浅,下面给出全部代码和源码:

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import com.bingo.customer.R;

import java.util.ArrayList;

/**
 * ================================
 * 作   者:   zcb
 * 邮   箱:   zhang-cb@foxmail.com
 * 创建时间:   2017/6/5 14:18
 * 版   本:   1.0
 * 描   述:   自定义芝麻分数等级view
 * 首先需要设置数据setdata,data中值的范围需要从小到大排序
 * 然后设置等级的值setCurrentDialvalue,即可
 * =================================
 */

public class UserLevelView extends View {
    private Context context;
    private String Tag = "UserLevelView";
    private Paint paint_bg = new Paint();
    private Paint paint_text_value = new Paint();
    private Paint paint_text_total = new Paint();
    private Paint hanziPaint = new Paint();
    private Paint recPaint = new Paint();

    private LinearGradient linearGradient;
    private ArrayList<UserLevelDial> datas;
    private int currentDialvalue = -1;
    //整个控件的长度
    private int allLength;
    //有背景文字的等级汉字的长度
    private int cDialLenth;

    //笔触宽度
    private int cap = 10;
    //进度条宽度
    private int lineWidth = 15;

    private int[] level_num = {350, 550, 600, 650, 700, 950};
    private int currentImg = -1;
    //图片等级与线条的间距
    private int padding_img = 20;
    //线条与上面文字的间距
    private int padding_text = 20;
    private int textHeight = 0;
    private int textSize;
    private int maxValue = 1500;
    private String[] paintString = {getResources().getString(R.string.text_sesame_level_jiaocha),
            getResources().getString(R.string.text_sesame_level_zhongdeng),
            getResources().getString(R.string.text_sesame_level_lianghao),
            getResources().getString(R.string.text_sesame_level_youxiu),
            getResources().getString(R.string.text_sesame_level_jihao)};

    private ArrayList<LineColor> lineColors = new ArrayList<>();

    public UserLevelView(Context context) {
        this(context, null);
        this.context = context;
    }

    public UserLevelView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
        this.context = context;
    }

    public UserLevelView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        this.context = context;
        init();
    }

    public void init() {
        this.textSize = DensityUtil.dip2px(getContext(), 10f);
        this.textHeight = getTextWH("9", textSize).height();
        initPaint();
        initLineColor();
    }


    public void initPaint() {

        //第二条背景线的画笔
        paint_bg.setColor(ContextCompat.getColor(context, R.color.gray));
        paint_bg.setStyle(Paint.Style.FILL);
//        paint_bg.setStrokeCap(Paint.Cap.ROUND);
        paint_bg.setStrokeJoin(Paint.Join.ROUND);
        paint_bg.setStrokeWidth(lineWidth);
        paint_bg.setAntiAlias(true);

        //选中值后的有颜色背景的汉字画笔
        paint_text_value.setTextSize(textSize);
        paint_text_value.setColor(ContextCompat.getColor(context, R.color.userlevels2));
        paint_text_total.setTextSize(textSize);
        paint_text_total.setColor(Color.BLACK);

        //汉字画笔
        hanziPaint.setStrokeWidth(3);
        hanziPaint.setTextSize(textSize);
        hanziPaint.setColor(Color.GRAY);
        hanziPaint.setTextAlign(Paint.Align.LEFT);
        hanziPaint.setAntiAlias(true);

        //渐变色矩形画笔
        recPaint.setStyle(Paint.Style.FILL);//充满
        recPaint.setColor(Color.LTGRAY);
        recPaint.setAntiAlias(true);// 设置画笔的锯齿效果
    }

    private void initLineColor() {
        lineColors.add(new LineColor(ContextCompat.getColor(context, R.color.jiaocha_start), ContextCompat.getColor(context, R.color.jiaocha_end)));
        lineColors.add(new LineColor(ContextCompat.getColor(context, R.color.zhongdeng_start), ContextCompat.getColor(context, R.color.zhongdeng_end)));
        lineColors.add(new LineColor(ContextCompat.getColor(context, R.color.lianghao_start), ContextCompat.getColor(context, R.color.lianghao_end)));
        lineColors.add(new LineColor(ContextCompat.getColor(context, R.color.youxiu_start), ContextCompat.getColor(context, R.color.youxiu_end)));
        lineColors.add(new LineColor(ContextCompat.getColor(context, R.color.jihao_start), ContextCompat.getColor(context, R.color.jihao_end)));
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int height = getPaddingTop() + getPaddingBottom() + lineWidth + padding_img + 20 + textHeight + padding_text;
        Log.i(Tag, "height:" + height);
        Log.i(Tag, "getPaddingBottom():" + getPaddingBottom() + ",getPaddingTop():" + getPaddingTop() + "padding_img:" + padding_img + "lineWidth" + lineWidth);
        setMeasuredDimension(getMeasuredWidth(), height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画第一行 5个等级的文字
        Rect rect = getTextWH(currentDialvalue + "", textSize);
        //修正边界
        Log.i(Tag, "textgetPaddingTop:" + getPaddingTop());
        int text_ph = getPaddingTop() + rect.height() - 7;

        if (currentDialvalue >= 350 && currentDialvalue < 550) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.jiaocha_start));
            draw5Characters(canvas, 1,  text_ph);
        } else if (currentDialvalue >= 550 && currentDialvalue < 600) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.zhongdeng_start));
            draw5Characters(canvas, 2,  text_ph);
        } else if (currentDialvalue >= 600 && currentDialvalue < 650) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.lianghao_start));
            draw5Characters(canvas, 3, text_ph);
        } else if (currentDialvalue >= 650 && currentDialvalue < 700) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.youxiu_start));
            draw5Characters(canvas, 4,  text_ph);
        } else if (currentDialvalue >= 700 && currentDialvalue < 950) {
            recPaint.setColor(ContextCompat.getColor(context, R.color.jihao_start));
            draw5Characters(canvas, 5, text_ph);
        }

        //画第二行不同颜色矩形
        int bgline_ph = lineWidth / 2 + 1 + getPaddingTop() + textHeight + padding_text;
        draw5Line(canvas, bgline_ph);
        //画第三行等级数字
        drawLevelNum(canvas);
    }

    /**
     * 画第一行5个等级词语{较差,中等,良好,优秀,极好}
     * @param canvas 画布
     * @param index 第一个需要背景
     * @param text_ph 高
     */
    public void draw5Characters(Canvas canvas, int index, int text_ph) {

        final float stepWidth = (getMeasuredWidth() - getPaddingRight() - cap) / 5;
        final float offsetWidth = getPaddingLeft() + stepWidth / 3;

        for (int i = 1; i <= 5; i++) {
            if (i == index) {
                // 背景矩形
                float left = stepWidth * (i - 1) + offsetWidth - 15;
                float top = getPaddingTop() - 20;
                float right = left + getTextWH("测试", textSize).width() + 30;
                float bottom = text_ph + 15;
                RectF oval3 = new RectF(left, top, right, bottom);
                canvas.drawRoundRect(oval3, 6, 6, recPaint);

                /**
                 * 三角形
                 *  *******
                 *   *****
                 *    ***
                 *     *
                 */
                Path path = new Path();
                path.moveTo(left, getPaddingTop());// 三角形的起顶点
                path.lineTo(right, getPaddingTop());//三角形右边的顶点
                path.lineTo((left + right) / 2, bottom + 10);  //三角形下面的顶点
                path.close(); // 使这些点构成封闭的多边形
                canvas.drawPath(path, recPaint);

                paint_text_value.setColor(Color.WHITE);
                canvas.drawText(paintString[i - 1], stepWidth * (i - 1) + offsetWidth, text_ph, paint_text_value);

            } else {
                canvas.drawText(paintString[i - 1], stepWidth * (i - 1) + offsetWidth, text_ph, hanziPaint);
            }
        }
    }

    /**
     * 画第二行5条等级颜色渐变线
     */
    public void draw5Line(Canvas canvas, int bgline_ph) {
        float startXPoint;
        float stopXPoint;
        float tempXPoint;

        for (int i = 1; i <= 5; i++) {
            startXPoint = (getMeasuredWidth() - getPaddingRight() - cap) / 5 * (i - 1) + getPaddingLeft();
            stopXPoint = (getMeasuredWidth() - getPaddingRight() - cap) / 5 * i + getPaddingLeft();
            if (i % 2 == 0) {  //第偶数次循环,交换起始点
                tempXPoint = startXPoint;
                startXPoint = stopXPoint;
                stopXPoint = tempXPoint;
            }

            linearGradient = new LinearGradient(startXPoint, 0, stopXPoint, 0, new int[]{lineColors.get(i - 1).startColor, lineColors.get(i - 1).stopColor}, null, LinearGradient.TileMode.CLAMP);
            paint_bg.setShader(linearGradient);
            canvas.drawLine(startXPoint, bgline_ph, stopXPoint, bgline_ph, paint_bg);
        }
    }

    /**
     * 画第三行的等级数字{350,550,600,650,70,950}
     *
     * @param canvas
     */
    public void drawLevelNum(Canvas canvas) {
        Paint mPaint = new Paint();
        mPaint.setStrokeWidth(3);
        mPaint.setTextSize(25);
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.GRAY);
        mPaint.setTextAlign(Paint.Align.CENTER);

        int img_postion_h = lineWidth + padding_img + getPaddingTop() + textHeight + padding_text;
        Log.i(Tag, "img_postion_h:" + img_postion_h);
        float pre = allLength / 5;
        float offsetw = 20 / 3 * -1;
        for (int i = 0; i < level_num.length; i++) {
            if (i == level_num.length - 1) {
                canvas.drawText(level_num[i] + "", allLength + getPaddingLeft() + cap, img_postion_h + 25, mPaint);
            } else {
                if (i == 0) {
                    canvas.drawText(level_num[i] + "", i * pre + getPaddingLeft() + cap, img_postion_h + 25, mPaint);
                } else {
                    canvas.drawText(level_num[i] + "", i * pre + offsetw + getPaddingLeft() + cap + 20, img_postion_h + 25, mPaint);
                }
            }
        }
    }


    /**
     * 设置有多少个刻度,每个刻度的返回{0,50},{50,x},{x,x2}....
     * 必须按照大小排好序再传递进来
     */
    public void setData(ArrayList<UserLevelDial> datas) {
        this.datas = datas;
        if (null != datas && datas.size() > 0) {
            maxValue = datas.get(datas.size() - 1).dial_e;
        }
    }

    //数值变化的动画
    ValueAnimator valueAnimator;

    /**
     * 设置当前刻度
     */
    public void setCurrentDialvalue(int dial) {
        if (null != valueAnimator && valueAnimator.isRunning()) {
            valueAnimator.cancel();
        }
        valueAnimator = ValueAnimator.ofInt(0, dial);
        valueAnimator.setDuration(5);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                currentDialvalue = (int) valueAnimator.getAnimatedValue();
                getCurrentDialLength();
                invalidate();
            }
        });
        valueAnimator.start();
    }

    //根据当前值,按照比例,计算它该有的长度,每个刻度的长度一样,但是每个刻度的差值不一样,
    //这里就根据比例来计算
    public int getCurrentDialLength() {
        getDialAllLength();
        if (allLength > 0 && datas.size() > 0 && currentDialvalue > 0) {
            int pre = allLength / (datas.size());
            for (int i = 0; i < datas.size(); i++) {
                UserLevelDial dial = datas.get(i);
                if (currentDialvalue <= dial.dial_e && currentDialvalue >= dial.dial_s) {
                    this.currentImg = i;
                    cDialLenth = pre * i + (int) (pre * ((currentDialvalue - dial.dial_s) / ((float) dial.dial_e - dial.dial_s)));
                    Log.i(Tag, "i:" + i);
                    break;
                }
            }
        }
        if (currentDialvalue > datas.get(datas.size() - 1).dial_e) {
            this.currentImg = datas.size();
            cDialLenth = allLength;
        }
        Log.i(Tag, "cDialLenth:" + cDialLenth);
        //重新设置等级图片
        return cDialLenth;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        getDialAllLength();
    }

    //得到整个长度,出去padding
    public void getDialAllLength() {
        allLength = getMeasuredWidth() - getPaddingLeft() - getPaddingRight() - cap * 2;
    }

    /**
     * @param text
     * @param textSize
     * @return
     */
    public Rect getTextWH(String text, int textSize) {
        Paint pFont = new Paint();
        Rect rect = new Rect();
        pFont.setTextSize(textSize);
        pFont.getTextBounds(text, 0, text.length(), rect);
        return rect;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        Log.i(Tag, "onDetachedFromWindow");
    }


    public class LineColor {

        public LineColor(int startColor, int stopColor) {
            this.startColor = startColor;
            this.stopColor = stopColor;
        }

        public int startColor;
        public int stopColor;
    }
}

 

  

源码如下:https://github.com/zhangchunbin/Demo_Customer_view

 

 

 

 

 

 

posted @ 2017-03-29 16:52  客舍青  阅读(428)  评论(0编辑  收藏  举报