Android自定义View之CircleView

前言

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

Android自定义View之CircleView-LMLPHP

分析

需求

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的用法。如文中有描述不巧当的地方请指出,谢谢。

04-30 04:35