Android開發自定義控制元件實現一個餅狀圖
實現一個如圖所示的控制元件,包括兩部分,左邊的餅狀圖和中間的兩個小方塊,及右邊的兩行文字
實現起來比較簡單,只是一些繪圖API的呼叫
核心程式碼在onDraw函式裡邊,,對靜態控制元件進行繪製即可
@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); }Canvas 繪製文字時,使用FontMetrics物件,計算位置的座標。參考:http://blog.csdn.net/tianjf0514/article/details/7642656
設定文字繪製以中心為起點開始繪製
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();
}
}
相關文章
- Android自定義View,畫一個好看帶延長線的餅狀圖AndroidView
- Flutter 112: 圖解自定義 ACEPieWidget 餅狀圖Flutter圖解
- 自定義View合輯(2)-餅狀圖View
- VirtualView Android 實現詳解(三)—— 新增一個自定義控制元件ViewAndroid控制元件
- android 自定義帶動畫的統計餅圖Android動畫
- Android 折線圖之hellocharts (餅狀圖)餅圖Android
- Flutter 自定義 Widget 之餅形圖實戰Flutter
- 如何開發一個百分比餅狀圖動畫動畫
- Qt實現自定義控制元件QT控制元件
- Android 自定義帶動畫的柱狀圖Android動畫
- Android自定義拍照實現Android
- 從Android到ReactNative開發(三、自定義原生控制元件支援)AndroidReact控制元件
- Android開發之自定義隨機驗證碼控制元件Android隨機控制元件
- Android自定義View--翻書控制元件(一)AndroidView控制元件
- 【Android】自定義樹形控制元件Android控制元件
- 從 Android 到 React Native 開發(三、自定義原生控制元件支援)AndroidReact Native控制元件
- android 自定義狀態列和導航欄分析與實現Android
- echart使用自定義單個柱狀顏色實現
- 自定義檢視---圓角柱狀圖(一)
- echarts 餅圖巢狀 二級餅圖 子餅圖 複合餅圖Echarts巢狀
- 如何開發FineReport的自定義控制元件?控制元件
- Android自定義控制元件(高手級)--JOJO同款能力分析圖Android控制元件
- Android自定義控制元件(高手級)–JOJO同款能力分析圖Android控制元件
- QT實現可拖動自定義控制元件QT控制元件
- 自定義一個下拉重新整理控制元件控制元件
- 餅圖元件的基本使用和自定義調整元件
- Android自定義控制元件之區域性圖片放大鏡–BiggerViewAndroid控制元件View
- Android自定義控制元件之區域性圖片放大鏡--BiggerViewAndroid控制元件View
- 微信小程式Tree自定義控制元件實現微信小程式控制元件
- Android 控制元件架構與自定義控制元件詳解Android控制元件架構
- 【android】自定義佈局控制控制元件的位置可以通過繼承FrameLayout實現Android控制元件繼承
- canvas簡單封裝一個echarts實現不了的餅圖Canvas封裝Echarts
- Android自定義控制元件(神級)+MediaRecoder錄音Android控制元件
- Android自定義多宮格解鎖控制元件Android控制元件
- Android自定義控制元件 帶文字提示的SeekBarAndroid控制元件
- 【Android初級】如何實現一個有動畫效果的自定義下拉選單Android動畫
- 工作記錄--WPF自定義控制元件,實現一個可設定編輯模式的TextBox控制元件模式
- vue實現一個動效柱狀圖Vue
- 永宏BI 自定義繪圖(環狀圖)繪圖