Android自定義控件實(shí)現(xiàn)餅狀圖
本文實(shí)現(xiàn)一個(gè)如圖所示的控件,包括兩部分,左邊的餅狀圖和中間的兩個(gè)小方塊,及右邊的兩行文字

實(shí)現(xiàn)起來比較簡單,只是一些繪圖API的調(diào)用
核心代碼在onDraw函數(shù)里邊,對靜態(tài)控件進(jìn)行繪制即可
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 餅狀圖的x坐標(biāo)
*/
float centreX= getWidth()/5;
/**
* 餅狀圖的y坐標(biāo)
*/
float centreY= getHeight()/2;
/**
* 文字的大小
*/
float textSize=getHeight()/7;
float width=(float)getWidth();
float height=(float)getHeight();
/**
* 中間小正方形邊長的一半
*/
float halfSmallRec =((float)getHeight())*3/70;
percent =((float) mBigBallNumber)/(mBigBallNumber + mSmallBallNumber);
/**
* 求餅狀圖的半徑
*/
radius= Math.min(getWidth() * 1 / 8, getHeight() * 10 / 35);
/**
* 構(gòu)建一個(gè)正方形,餅狀圖是這個(gè)正方形的內(nèi)切圓
*/
rectf=new RectF((int)(centreX-radius),(int)(centreY-radius),(int)(centreX+radius),(int)(centreY+radius));
/**
* 設(shè)置餅狀圖畫筆的顏色,先繪制大球占的比例
*/
piePaint.setColor(mBigBallColor);
/* The arc is drawn clockwise. An angle of 0 degrees correspond to the
* geometric angle of 0 degrees (3 o'clock on a watch.)*/
/* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)*/
/**
* 繪制大球的扇形圖,float startAngle起始角度的0度的位置在3點(diǎn)鐘方向
* 因此大球的扇形圖要從12點(diǎn)鐘開始繪制,所以起始角度為270度
*/
canvas.drawArc(rectf, 270, 360 * percent, true, piePaint);
/**
* 換種顏色,開始繪制小球占的餅狀圖
*/
piePaint.setColor(mSmallBallColor);
/**
* 起始角度就是12點(diǎn)鐘加上360度乘以大球占的比例,12點(diǎn)鐘轉(zhuǎn)換為起始角度為270度
*/
canvas.drawArc(rectf, 270 + 360 * percent, 360 - 360 * percent, true, piePaint);
顏色更改為大球的顏色*/
piePaint.setColor(mBigBallColor);
/**
* 繪制上邊的小方塊,也就是大球的方塊
*/
canvas.drawRect(width * 2 / 5 - halfSmallRec, height* 23/ 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height *23/ 60 + halfSmallRec, piePaint);
/**
* 更改畫筆顏色為小球顏色
*/
piePaint.setColor(mSmallBallColor);
/**
* 繪制下邊的小方塊即小球的小方塊
*/
canvas.drawRect(width * 2 / 5 - halfSmallRec, height * 37 / 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height * 37 / 60 + halfSmallRec, piePaint);
/**
* 開始繪制文字,先設(shè)置文字顏色
*/
textPaint.setColor(getResources().getColor(typedValue.resourceId));
/**
* 設(shè)置問題大小
*/
textPaint.setTextSize(textSize);
/**
* 大球數(shù)量
*/
String strBig = strBigBallName + mBigBallNumber;
/**
* 測量文字寬度
*/
float textBigWidth =textPaint.measureText(strBig);
Paint.FontMetrics fontMetrics=textPaint.getFontMetrics();
/**
* 繪制上邊大球數(shù)量
*/
canvas.drawText(strBig, width * 9 / 20 + textBigWidth / 2, height *23/ 60 - fontMetrics.top / 3, textPaint);
/**
* 小球數(shù)量
*/
String strSmall = strSmallBallName + mSmallBallNumber;
/**
* 測量文字寬度
*/
float textUnderWidth=textPaint.measureText(strSmall);
/**
* 繪制下邊的小球數(shù)量
*/
canvas.drawText(strSmall,width*9/20+textUnderWidth/2,height*37/60-fontMetrics.top/3,textPaint);
/**
* 更改畫筆顏色,開始繪制百分比
*/
textPaint.setColor(getResources().getColor(R.color.half_transparent));
String strBigPercent =" ("+ mPercentBigBall +")";
/**
* 測量大球百分比文字寬度
*/
float bigPercent =textPaint.measureText(strBigPercent);
/**drawText(String text, float x, float y, Paint paint)
* 繪制文字的API,四個(gè)參數(shù)分別是文字內(nèi)容,起始繪制x坐標(biāo),起始繪制y坐標(biāo),畫筆
* 以為設(shè)置了居中繪制,因此穿進(jìn)去的xy坐標(biāo)為文字的中心點(diǎn)
*/
canvas.drawText(strBigPercent, width * 9 / 20+ textBigWidth + bigPercent /2, height*23 / 60-fontMetrics.top*1/3, textPaint);
/**
* 同樣的道理繪制小球的百分比
*/
String strSmallPercent =" ("+ mPercentSmallBall +")";
float smallPercent =textPaint.measureText(strSmallPercent);
canvas.drawText(strSmallPercent,width*9/20+textUnderWidth+ smallPercent /2,height*37/60-fontMetrics.top/3,textPaint);
}
Canvas 繪制文本時(shí),使用FontMetrics對象,計(jì)算位置的坐標(biāo)。參考:使用FontMetrics對象計(jì)算位置坐標(biāo)

設(shè)置文字繪制以中心為起點(diǎn)開始繪制
textPaint.setTextAlign(Paint.Align.CENTER);
x的坐標(biāo)好計(jì)算,y坐標(biāo)需要按需使用FontMetrics幾個(gè)屬性即可
完整代碼如下:
public class PieHalfView extends View {
/**
* 左邊餅狀圖的畫筆
*/
private Paint piePaint;
/**
* 右邊文字的畫筆
*/
private Paint textPaint;
/**
* 餅狀圖的半徑
*/
private float radius;
private RectF rectf;
/**
* 餅狀圖中第一個(gè)扇形占整個(gè)圓的比例
*/
private float percent;
/**
* 深淺兩種顏色
*/
private int mBigBallColor, mSmallBallColor;
/**
* 大小球的數(shù)量
*/
private int mBigBallNumber;
private int mSmallBallNumber;
/**
* 大小球所占的百分比
*/
private String mPercentBigBall;
private String mPercentSmallBall;
/**
* 動(dòng)態(tài)獲取屬性
*/
private TypedValue typedValue;
/**
* 中間的文字信息
*/
private String strBigBallName;
private String strSmallBallName;
public PieHalfView(Context context) {
super(context);
init(context);
}
public PieHalfView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public PieHalfView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context);
}
private void init(Context context) {
/**
* 設(shè)置餅狀圖畫筆
*/
piePaint =new Paint();
piePaint.setAntiAlias(true);
piePaint.setStyle(Paint.Style.FILL);
/**
* 設(shè)置文字畫筆
*/
textPaint=new Paint();
textPaint.setStyle(Paint.Style.STROKE);
textPaint.setAntiAlias(true);
textPaint.setTextAlign(Paint.Align.CENTER);
/**
* 下邊設(shè)置一些默認(rèn)的值,如果調(diào)用者沒有傳值進(jìn)來的話,用這些默認(rèn)值
*/
mBigBallColor = 0xFF9CCA5D;
mSmallBallColor =0xFF5F7048;
/*TypedValue:Container for a dynamically typed data value. Primarily used with Resources for holding resource values.*/
typedValue=new TypedValue();
context.getTheme().resolveAttribute(R.attr.maintextclor,typedValue,true);
mBigBallNumber =1;
mSmallBallNumber =3;
mPercentBigBall ="40%";
mPercentSmallBall ="60%";
strBigBallName =getResources().getString(R.string.big);
strSmallBallName =getResources().getString(R.string.small);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
/**
* 餅狀圖的x坐標(biāo)
*/
float centreX= getWidth()/5;
/**
* 餅狀圖的y坐標(biāo)
*/
float centreY= getHeight()/2;
/**
* 文字的大小
*/
float textSize=getHeight()/7;
float width=(float)getWidth();
float height=(float)getHeight();
/**
* 中間小正方形邊長的一半
*/
float halfSmallRec =((float)getHeight())*3/70;
percent =((float) mBigBallNumber)/(mBigBallNumber + mSmallBallNumber);
/**
* 求餅狀圖的半徑
*/
radius= Math.min(getWidth() * 1 / 8, getHeight() * 10 / 35);
/**
* 構(gòu)建一個(gè)正方形,餅狀圖是這個(gè)正方形的內(nèi)切圓
*/
rectf=new RectF((int)(centreX-radius),(int)(centreY-radius),(int)(centreX+radius),(int)(centreY+radius));
/**
* 設(shè)置餅狀圖畫筆的顏色,先繪制大球占的比例
*/
piePaint.setColor(mBigBallColor);
/* The arc is drawn clockwise. An angle of 0 degrees correspond to the
* geometric angle of 0 degrees (3 o'clock on a watch.)*/
/* drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter,Paint paint)*/
/* 繪制大球的扇形圖,float startAngle起始角度的0度的位置在3點(diǎn)鐘方向
* 因此大球的扇形圖要從12點(diǎn)鐘開始繪制,所以起始角度為270度*/
canvas.drawArc(rectf, 270, 360 * percent, true, piePaint);
/**
* 換種顏色,開始繪制小球占的餅狀圖
*/
piePaint.setColor(mSmallBallColor);
/**
* 起始角度就是12點(diǎn)鐘加上360度乘以大球占的比例,12點(diǎn)鐘轉(zhuǎn)換為起始角度為270度
*/
canvas.drawArc(rectf, 270 + 360 * percent, 360 - 360 * percent, true, piePaint);
/**
* 顏色更改為大球的顏色*/
piePaint.setColor(mBigBallColor);
/**
* 繪制上邊的小方塊,也就是大球的方塊
*/
canvas.drawRect(width * 2 / 5 - halfSmallRec, height* 23/ 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height *23/ 60 + halfSmallRec, piePaint);
/**
* 更改畫筆顏色為小球顏色
*/
piePaint.setColor(mSmallBallColor);
/**
* 繪制下邊的小方塊即小球的小方塊
*/
canvas.drawRect(width * 2 / 5 - halfSmallRec, height * 37 / 60 - halfSmallRec, width * 2 / 5 + halfSmallRec, height * 37 / 60 + halfSmallRec, piePaint);
/**
* 開始繪制文字,先設(shè)置文字顏色
*/
textPaint.setColor(getResources().getColor(typedValue.resourceId));
/**
* 設(shè)置問題大小
*/
textPaint.setTextSize(textSize);
/**
* 大球數(shù)量
*/
String strBig = strBigBallName + mBigBallNumber;
/**
* 測量文字寬度
*/
float textBigWidth =textPaint.measureText(strBig);
Paint.FontMetrics fontMetrics=textPaint.getFontMetrics();
/**
* 繪制上邊大球數(shù)量
*/
canvas.drawText(strBig, width * 9 / 20 + textBigWidth / 2, height *23/ 60 - fontMetrics.top / 3, textPaint);
/**
* 小球數(shù)量
*/
String strSmall = strSmallBallName + mSmallBallNumber;
/**
* 測量文字寬度
*/
float textUnderWidth=textPaint.measureText(strSmall);
/**
* 繪制下邊的小球數(shù)量
*/
canvas.drawText(strSmall,width*9/20+textUnderWidth/2,height*37/60-fontMetrics.top/3,textPaint);
/**
* 更改畫筆顏色,開始繪制百分比
*/
textPaint.setColor(getResources().getColor(R.color.half_transparent));
String strBigPercent =" ("+ mPercentBigBall +")";
/**
* 測量大球百分比文字寬度*/
float bigPercent =textPaint.measureText(strBigPercent);
/** drawText(String text, float x, float y, Paint paint)
* 繪制文字的API,四個(gè)參數(shù)分別是文字內(nèi)容,起始繪制x坐標(biāo),起始繪制y坐標(biāo),畫筆
* 以為設(shè)置了居中繪制,因此穿進(jìn)去的xy坐標(biāo)為文字的中心點(diǎn)
*/
canvas.drawText(strBigPercent, width * 9 / 20+ textBigWidth + bigPercent /2, height*23 / 60-fontMetrics.top*1/3, textPaint);
/*
* 同樣的道理繪制小球的百分比
*/
String strSmallPercent =" ("+ mPercentSmallBall +")";
float smallPercent =textPaint.measureText(strSmallPercent);
canvas.drawText(strSmallPercent,width*9/20+textUnderWidth+ smallPercent /2,height*37/60-fontMetrics.top/3,textPaint);
}
public void setPercent(float percent1){
this.percent =percent1;
invalidate();
}
public void setColor(int mBigBallColor,int mSmallBallColor){
this.mBigBallColor =mBigBallColor;
this.mSmallBallColor =mSmallBallColor;
invalidate();
}
public void setOverRunner(String bigPecent, String smallPercent, int big, int small,
int bigColor, int smallColor){
this.mPercentBigBall = bigPecent;
this.mPercentSmallBall = smallPercent;
this.mBigBallNumber = big;
this.mSmallBallNumber = small;
this.mBigBallColor = bigColor;
this.mSmallBallColor = smallColor;
invalidate();
}
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android Flutter實(shí)戰(zhàn)之為照片添加顏色濾鏡
這篇文章我們將利用TweenAnimationBuilder來實(shí)現(xiàn)一個(gè)圖片調(diào)色的過渡動(dòng)畫,從而實(shí)現(xiàn)為照片添加顏色濾鏡的效果,感興趣的可以了解一下2022-12-12
Android Compose 屬性動(dòng)畫使用探索詳解
這篇文章主要為大家介紹了Android Compose 屬性動(dòng)畫使用探索詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
android自定義控件實(shí)現(xiàn)簡易時(shí)間軸(1)
這篇文章主要為大家詳細(xì)介紹了android自定義控件實(shí)現(xiàn)簡易時(shí)間軸,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
Android編程實(shí)現(xiàn)兩點(diǎn)觸控功能示例
這篇文章主要介紹了Android編程實(shí)現(xiàn)兩點(diǎn)觸控功能的方法,涉及Android事件響應(yīng)與處理相關(guān)操作技巧,需要的朋友可以參考下2017-08-08
Android實(shí)現(xiàn)閃屏及注冊和登錄界面之間的切換效果
這篇文章主要介紹了Android實(shí)現(xiàn)閃屏及注冊和登錄界面之間的切換效果,實(shí)現(xiàn)思路是先分別實(shí)現(xiàn)閃屏、注冊界面、登錄界面的活動(dòng),再用Intent將相關(guān)的活動(dòng)連接起來,實(shí)現(xiàn)不同活動(dòng)之間的跳轉(zhuǎn),對android 實(shí)現(xiàn)閃屏和界面切換感興趣的朋友一起看看吧2016-11-11

