Android自定義View之CircleView
版權聲明:本文為博主原創文章,未經博主允許不得轉載。
前言
大家好,我是Cavalier,這次和大家分享一下《Android自定義View之CircleView》,不廢話,下面上效果圖。

分析
需求
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的用法。如文中有描述不巧當的地方請指出,謝謝。
