Android開發自定義控制元件實現一個餅狀圖
阿新 • • 發佈:2019-02-07
實現一個如圖所示的控制元件,包括兩部分,左邊的餅狀圖和中間的兩個小方塊,及右邊的兩行文字
實現起來比較簡單,只是一些繪圖API的呼叫
核心程式碼在onDraw函式裡邊,,對靜態控制元件進行繪製即可
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); /*餅狀圖的x座標*/ float centreX= getWidth()/5; /*餅狀圖的y座標*/ float centreY= getHeight()/2; /*文字的大小*/ float textSize=getHeight()/Canvas 繪製文字時,使用FontMetrics物件,計算位置的座標。參考:http://blog.csdn.net/tianjf0514/article/details/76426567; 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); /*構建一個正方形,餅狀圖是這個正方形的內切圓*/rectf=new RectF((int)(centreX-radius),(int)(centreY-radius),(int)(centreX+radius),(int)(centreY+radius)); /*設定餅狀圖畫筆的顏色,先繪製大球佔的比例*/ 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點鐘方向 * 因此大球的扇形圖要從12點鐘開始繪製,所以起始角度為270度*/ canvas.drawArc(rectf, 270, 360 * percent, true, piePaint); /*換種顏色,開始繪製小球佔的餅狀圖*/ piePaint.setColor(mSmallBallColor); /*起始角度就是12點鐘加上360度乘以大球佔的比例,12點鐘轉換為起始角度為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); /*開始繪製文字,先設定文字顏色*/ textPaint.setColor(getResources().getColor(typedValue.resourceId)); /*設定問題大小*/ textPaint.setTextSize(textSize); /*大球數量*/ String strBig = strBigBallName + mBigBallNumber; /*測量文字寬度*/ float textBigWidth =textPaint.measureText(strBig); Paint.FontMetrics fontMetrics=textPaint.getFontMetrics(); /*繪製上邊大球數量*/ canvas.drawText(strBig, width * 9 / 20 + textBigWidth / 2, height *23/ 60 - fontMetrics.top / 3, textPaint); /*小球數量*/ String strSmall = strSmallBallName + mSmallBallNumber; /*測量文字寬度*/ float textUnderWidth=textPaint.measureText(strSmall); /*繪製下邊的小球數量*/ 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,四個引數分別是文字內容,起始繪製x座標,起始繪製y座標,畫筆 * 以為設定了居中繪製,因此穿進去的xy座標為文字的中心點*/ 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); }
設定文字繪製以中心為起點開始繪製
textPaint.setTextAlign(Paint.Align.CENTER);
x的座標好計算,y座標需要按需使用FontMetrics幾個屬性即可
完整程式碼如下:
public class PieHalfView extends View {
/*左邊餅狀圖的畫筆*/
private Paint piePaint;
/*右邊文字的畫筆*/
private Paint textPaint;
/*餅狀圖的半徑*/
private float radius;
private RectF rectf;
/*餅狀圖中第一個扇形佔整個圓的比例*/
private float percent;
/*深淺兩種顏色*/
private int mBigBallColor, mSmallBallColor;
/*大小球的數量*/
private int mBigBallNumber;
private int mSmallBallNumber;
/*大小球所佔的百分比*/
private String mPercentBigBall;
private String mPercentSmallBall;
/*動態獲取屬性*/
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) {
/*設定餅狀圖畫筆*/
piePaint =new Paint();
piePaint.setAntiAlias(true);
piePaint.setStyle(Paint.Style.FILL);
/*設定文字畫筆*/
textPaint=new Paint();
textPaint.setStyle(Paint.Style.STROKE);
textPaint.setAntiAlias(true);
textPaint.setTextAlign(Paint.Align.CENTER);
/*下邊設定一些預設的值,如果呼叫者沒有傳值進來的話,用這些預設值*/
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座標*/
float centreX= getWidth()/5;
/*餅狀圖的y座標*/
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);
/*構建一個正方形,餅狀圖是這個正方形的內切圓*/
rectf=new RectF((int)(centreX-radius),(int)(centreY-radius),(int)(centreX+radius),(int)(centreY+radius));
/*設定餅狀圖畫筆的顏色,先繪製大球佔的比例*/
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點鐘方向
* 因此大球的扇形圖要從12點鐘開始繪製,所以起始角度為270度*/
canvas.drawArc(rectf, 270, 360 * percent, true, piePaint);
/*換種顏色,開始繪製小球佔的餅狀圖*/
piePaint.setColor(mSmallBallColor);
/*起始角度就是12點鐘加上360度乘以大球佔的比例,12點鐘轉換為起始角度為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);
/*開始繪製文字,先設定文字顏色*/
textPaint.setColor(getResources().getColor(typedValue.resourceId));
/*設定問題大小*/
textPaint.setTextSize(textSize);
/*大球數量*/
String strBig = strBigBallName + mBigBallNumber;
/*測量文字寬度*/
float textBigWidth =textPaint.measureText(strBig);
Paint.FontMetrics fontMetrics=textPaint.getFontMetrics();
/*繪製上邊大球數量*/
canvas.drawText(strBig, width * 9 / 20 + textBigWidth / 2, height *23/ 60 - fontMetrics.top / 3, textPaint);
/*小球數量*/
String strSmall = strSmallBallName + mSmallBallNumber;
/*測量文字寬度*/
float textUnderWidth=textPaint.measureText(strSmall);
/*繪製下邊的小球數量*/
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,四個引數分別是文字內容,起始繪製x座標,起始繪製y座標,畫筆
* 以為設定了居中繪製,因此穿進去的xy座標為文字的中心點*/
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();
}
}