Android自定义View之CircleView

Android自定义View之CircleView

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载请表明出处:http://www.cnblogs.com/cavalier-/p/5999037.html

前言

大家好,我是Cavalier,这次和大家分享一下《Android自定义View之CircleView》,不废话,下面上效果图。

Alt text

分析

需求

1:随机换颜色的一个view  
2:可以设置文字

动手

Setup1:继承自View,重写三个构造函数

public class CircleView extends View {
    public CircleView(Context context) {
        this(context,null);
    }

    public CircleView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

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

上面代码中重写了三个构造函数,其中第一个是用于直接new对象,第二个是从xml创建时没有指定style时调用,第三个是指定了style时调用,通过this可以直接指向第三个构造参数,所有初始化可以直接写在第三个构造参数中

Setup2:声明所需的变量

private Paint mTextPain;                        //初始化画笔
private String mText = "";                      //初始化文字
private int radius;                             //当前View的半径

...
 public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    configPaint();
}
  
private void configPaint() {
    mTextPain = new Paint();
    mTextPain.setColor(Color.WHITE);            //设置画笔颜色为白色
    mTextPain.setAntiAlias(true);               //开启抗锯齿,平滑文字和圆弧的边缘
    mTextPain.setTextAlign(Paint.Align.CENTER); //设置文本位于相对于原点的中间
}

上面代码在第三个构造函数调用了configPaint函数

Setup3:重新onDraw函数

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int width = getWidth() / 2;                                 //获取宽度一半
    int height = getHeight() / 2;                               //获取高度一半
    radius = Math.min(width, height);                           //设置半径为宽或者高的最小值
    //paint bg
    mTextPain.setColor(Color.parseColor(getRandomColor()));     //设置画笔颜色为随机颜色
    canvas.drawCircle(width, height, radius, mTextPain);        //利用canvas画一个圆

    //paint font
    mTextPain.setColor(Color.WHITE);                            //设置画笔白颜色
    mTextPain.setTextSize(dp2px(16));                           //设置字体大小为16dp
    Paint.FontMetrics fontMetrics = mTextPain.getFontMetrics(); //获取字体测量对象
    canvas.drawText(mText, 0, mText.length(), radius            //利用canvas画上字
            , radius + Math.abs(fontMetrics.top + fontMetrics.bottom) / 2, mTextPain);
}

上面代码中先获取到当前view的宽和高,取其中最小值作为背景的半径,设置了随机颜色做背景,且利用FontMetrics获取了文字的绘制位置

Setup4:添加两个辅助函数,dp2px和getRandomColor

/**
 * 给View设置文字
 * @param str
 */
public void setText(String str) {
    if(!TextUtils.isEmpty(str)){
        if(str.length()>1){
            mText = str.substring(0,1);
        }else {
            mText = str;
        }
    }else {
        mText =  "";
    }
    invalidate();
}

当然,我们需要将设置文字暴露给使用者,这里利用了invalidate让CircleView重新绘制一遍,目的是更改内中的文字

Setup5:添加两个辅助函数,dp2px和getRandomColor

/**
 * dp转px
 *
 * @param dp
 * @return
 */
private int dp2px(int dp) {
    // px = dp * (dpi / 160)
    DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
    int dpi = metrics.densityDpi;
    return (int) (dp * (dpi / 160f) + 0.5f);
}


/**
 * 获取随机颜色
 *
 * @return
 */
private String getRandomColor() {
    List<String> colorList = new ArrayList<String>();
    colorList.add("#303F9F");
    colorList.add("#FF4081");
    colorList.add("#59dbe0");
    colorList.add("#f57f68");
    colorList.add("#f8b552");
    colorList.add("#990099");
    colorList.add("#90a4ae");
    colorList.add("#7baaf7");
    colorList.add("#4dd0e1");
    colorList.add("#4db6ac");
    colorList.add("#aed581");
    colorList.add("#fdd835");
    colorList.add("#f2a600");
    colorList.add("#ff8a65");
    colorList.add("#f48fb1");
    colorList.add("#7986cb");
    colorList.add("#DEB887");
    colorList.add("#FF69B4");
    return colorList.get((int) (Math.random() * colorList.size()));
}

补充了这两个辅助函数后,代码已经完成了

How to use?

在XML中使用

...

<com.ram.testdemo.view.CircleView
    android:id="@+id/cv"
    android:layout_width="50dp"
    android:layout_height="50dp"/>

...

这里注意调用时是使用你自己的Class文件全路径。

在java中使用

CircleView mCircleView = (CircleView) findViewById(R.id.cv);
mCircleView.setText("哈哈");

Souce Code

public class CircleView extends View {
    private Paint mTextPain;                        //初始化画笔
    private String mText = "";                      //初始化文字
    private int radius;                             //当前View的半径

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

    public CircleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

    private void configPaint() {
        mTextPain = new Paint();
        mTextPain.setColor(Color.WHITE);            //设置画笔颜色为白色
        mTextPain.setAntiAlias(true);               //开启抗锯齿,平滑文字和圆弧的边缘
        mTextPain.setTextAlign(Paint.Align.CENTER); //设置文本位于相对于原点的中间
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int width = getWidth() / 2;                                 //获取宽度一半
        int height = getHeight() / 2;                               //获取高度一半
        radius = Math.min(width, height);                           //设置半径为宽或者高的最小值
        //paint bg
        mTextPain.setColor(Color.parseColor(getRandomColor()));     //设置画笔颜色为随机颜色
        canvas.drawCircle(width, height, radius, mTextPain);        //利用canvas画一个圆

        //paint font
        mTextPain.setColor(Color.WHITE);                            //设置画笔白颜色
        mTextPain.setTextSize(dp2px(16));                           //设置字体大小为16dp
        Paint.FontMetrics fontMetrics = mTextPain.getFontMetrics(); //获取字体测量对象
        canvas.drawText(mText, 0, mText.length(), radius            //利用canvas画上字
                , radius + Math.abs(fontMetrics.top + fontMetrics.bottom) / 2, mTextPain);
    }

    /**
     * 给View设置文字
     * @param str
     */
    public void setText(String str) {
        if(!TextUtils.isEmpty(str)){
            if(str.length()>1){
                mText = str.substring(0,1);
            }else {
                mText = str;
            }
        }else {
            mText =  "";
        }
        invalidate();
    }

    /**
     * dp转px
     *
     * @param dp
     * @return
     */
    public int dp2px(int dp) {
        // px = dp * (dpi / 160)
        DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
        int dpi = metrics.densityDpi;
        return (int) (dp * (dpi / 160f) + 0.5f);
    }



    /**
     * 获取随机颜色
     *
     * @return
     */
    private String getRandomColor() {
        List<String> colorList = new ArrayList<String>();
        colorList.add("#303F9F");
        colorList.add("#FF4081");
        colorList.add("#59dbe0");
        colorList.add("#f57f68");
        colorList.add("#f8b552");
        colorList.add("#990099");
        colorList.add("#90a4ae");
        colorList.add("#7baaf7");
        colorList.add("#4dd0e1");
        colorList.add("#4db6ac");
        colorList.add("#aed581");
        colorList.add("#fdd835");
        colorList.add("#f2a600");
        colorList.add("#ff8a65");
        colorList.add("#f48fb1");
        colorList.add("#7986cb");
        colorList.add("#DEB887");
        colorList.add("#FF69B4");
        return colorList.get((int) (Math.random() * colorList.size()));
    }
}

结尾

本篇中,我们掌握了自定义View的invalidate重绘,和FontMetrics的文本位置测量,还了解onDraw中的canvas的用法。如文中有描述不巧当的地方请指出,谢谢。

参考 : Android custom-components

posted @ 2016-10-26 09:02  Cavalier-  阅读(2409)  评论(0编辑  收藏  举报