編輯:關於Android編程
單位項目要實現如下圖這種環形圖或是說特殊的餅形圖,在網上找了半天,沒有發現開源的,沒法子,只能硬著頭皮自己寫一個了。最近也在學習自定義view。正好拿這個來進行練習一下。
先分析一下功能,
1, 一共六個環形,每個顏色,弧度不同,
2, 在每個環形上,根據其環的弧度不同,在弧的中心點上,伸出線,在線上顯示相應的數值
3, 在線的結尾處,顯示一個圓角方形,內部是其百分比。
一,六個環形的畫法
一般在畫環形時,我們都是采用畫圈,然後設置其style為空心,給StrokeWidth一個值,用它來設置環的寬,可是這裡有一個問題,在設置完寬之後,它的這個寬是在邊為1的情況下,向內外擴展。說簡單一點,就是如果我們要畫一個半徑為100的環,如果你把StrokeWidth設成20,你會發現,最後畫出來的,是一個半徑為110的環。在這種情況下,我們在畫環上線的時候,算其長度會有麻煩。
我采用了一個比較笨的方法,就是畫一個實心圓,然後再畫一個半徑減去環寬的小圓,這樣就達到了圓環的效果。這樣還有一個好處是,中心的圓的顏色也可以自定義了。
這裡其實最麻煩的是算環形的半徑,這裡我一直也沒有想好有什麼太好的方法,我的方法比較笨,就是取控件的高度一半,然後再減去一個值,因為我認為,這個控件是一個寬大於高的控件,因為左右會有伸出的線嗎,所以相當來說,高就是比較小的哪個值,只所以還要減一個值,是因為要給線上的值,留一個空位出來,看一下效果圖,就明白什麼意思了。
二,環上的線
這裡我采用了三角函數進行計算弧的中心點,然後根據它的不同位置進行畫線,這裡無非就是八種情況,向右上折,向右全直,向右下折,垂直向下然後右直,重直向下左直,向左上折,向左全直,向左下折。而直線的長度,我是根據線上的文字的長度來確定,然後左右各留出10的寬度.
三,在線尾處畫圓角方形和百分比
前兩步做完,這一步就比較簡單了,采用drawRoundRect就可以很輕松的完成。
好了,分析到此為止,下面是代碼,裡面的注解比較清楚。
package com.example.cg.customcirclepre.custom; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.RectF; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import com.example.cg.customcirclepre.R; import java.text.DecimalFormat; /** * 帶動畫的自定義餅形圖 * 作者:cg * 時間:2016/9/6 0006 下午 2:48 */ public class AnimationCirPre extends View { private float iBNum = 150; //流入大單數 private int iBColor = Color.parseColor("#EE755C"); //流入大單顏色 private float iMNum = 200; //流入中單數 private int iMColor = Color.parseColor("#D7583E"); //流入中單顏色 private float iSNum = 180; //流入小單數 private int iSColor = Color.parseColor("#C73F23"); //流入小單顏色 private float oBNum = 660; //流出大單數 private int oBColor = Color.parseColor("#25D98E"); //流出大單顏色 private float oMNum = 210; //流出中單數 private int oMColor = Color.parseColor("#2EBA80"); //流出中單顏色 private float oSNum = 195; //流出小單數 private int oSColor = Color.parseColor("#1D8057"); //流出小單顏色 private int StrokeWidth = 150; //弧的寬度 private int TextSize = 50; //文字大小 private boolean isAnimation = false; //是否使用動畫效果 private int AnimationSpeed = 2; //動畫的速度 private int circleCenterColor = Color.parseColor("#ffffff"); //圓心顏色,默認是白色 private Paint mPaint; //畫筆 private RectF mRectf; //外圈圓的方形 private Rect mBound; //文字外框 private String txtNumPre; //顯示所占百分比 float[] point; //記錄弧度最外邊中心點的坐標 private int adjustDist = 20; //在弧度上面的線,為了調整其最好的顯示位置設置一個調整的距離數 private float txtBeginX = 0; //線上文字開始的位置的X坐標值 private float txtBeginY = 0; //線上文字開始的位置的y坐標值 private float txtEndX =0; //線上文字結束的位置的x坐標值 //計算總數 private float sum; //計算六個值的百分比 private float oBpre; private float oMpre; private float oSpre; private float iBpre; private float iMpre; private float iSpre; //計算六個值所占圓的弧度數 private float oBArc; private float oMArc; private float oSArc; private float iBArc; private float iMArc; private float iSArc; //六個值弧度的初始值 private float mOBArc = 1; private float mOMArc = 1; private float mOSArc = 1; private float mISArc = 1; private float mIMArc = 1; private float mIBArc = 1; public AnimationCirPre(Context context) { this(context,null); } public AnimationCirPre(Context context, AttributeSet attrs) { this(context, attrs,0); } public AnimationCirPre(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray array = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.MyPre, defStyleAttr, 0); int n = array.getIndexCount(); for(int i=0;i= oBArc) { DrawOB(canvas, radius, oBArc, oBpre); mPaint.setColor(oMColor); canvas.drawArc(mRectf, 270 + oBArc, mOMArc, true, mPaint); mOMArc = mOMArc + AnimationSpeed; if (mOMArc <= oMArc) { postInvalidate(); } } //第三個 if (mOMArc >= oMArc) { DrawOM(canvas, radius, oBArc, oMArc, oMpre); mPaint.setColor(oSColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc, mOSArc, true, mPaint); mOSArc = mOSArc + AnimationSpeed; if (mOSArc <= oSArc) { postInvalidate(); } } //第四個 if (mOSArc >= oSArc) { DrawOS(canvas, radius, oBArc + oMArc, oSArc, oSpre); mPaint.setColor(iSColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc + oSArc, mISArc, true, mPaint); mISArc = mISArc + AnimationSpeed; if (mISArc <= iSArc) { postInvalidate(); } } //第五個 if (mISArc >= iSArc) { DrawIS(canvas, radius, oBArc + oMArc + oSArc, iSArc, iSpre); mPaint.setColor(iMColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc + oSArc + iSArc, mIMArc, true, mPaint); mIMArc = mIMArc + AnimationSpeed; if (mIMArc <= iMArc) { postInvalidate(); } } //第六個 if (mIMArc >= iMArc ) { DrawIM(canvas, radius, oBArc + oMArc + oSArc + iSArc, iMArc, iMpre); mPaint.setColor(iBColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc + oSArc + iSArc + iMArc, mIBArc, true, mPaint); mIBArc = mIBArc + AnimationSpeed; if (mIBArc <= iBArc + 1) { postInvalidate(); } } if (mIBArc >= iBArc) { DrawIB(canvas, radius, oBArc + oMArc + oSArc + iSArc + iMArc, iBArc, iBpre); } }else { /** * 畫出六個扇面 */ mPaint.setColor(oBColor); canvas.drawArc(mRectf, 270, oBArc, true, mPaint); mPaint.setColor(oMColor); canvas.drawArc(mRectf, 270 + oBArc, oMArc, true, mPaint); mPaint.setColor(oSColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc, oSArc, true, mPaint); mPaint.setColor(iSColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc + oSArc, iSArc, true, mPaint); mPaint.setColor(iMColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc + oSArc + iSArc, iMArc, true, mPaint); mPaint.setColor(iBColor); canvas.drawArc(mRectf, 270 + oBArc + oMArc + oSArc + iSArc + iMArc, iBArc, true, mPaint); DrawOB(canvas, radius, oBArc, oBpre); DrawOM(canvas, radius, oBArc, oMArc, oMpre); DrawOS(canvas, radius, oBArc + oMArc, oSArc, oSpre); DrawIS(canvas, radius, oBArc + oMArc + oSArc, iSArc, iSpre); DrawIM(canvas, radius, oBArc + oMArc + oSArc + iSArc, iMArc, iMpre); DrawIB(canvas, radius, oBArc + oMArc + oSArc + iSArc + iMArc, iBArc, iBpre); } /** * 畫出中間的空白區域 */ mPaint.setColor(circleCenterColor); canvas.drawCircle(getWidth() / 2, getHeight() / 2, radius - StrokeWidth, mPaint); } /** * 流出大單 * @param canvas 畫板 * @param radius 中心半徑 * @param oBArc 流出大單弧度 * @param oBpre 流出大單百分比 */ public void DrawOB(Canvas canvas,float radius,float oBArc,float oBpre) { /** * 流出大單 */ if(oBNum>0) { //設置顯示的大單數量,在橫線上顯示的文字 mPaint.setColor(oBColor); mPaint.setTextSize(TextSize); String txt = "大單 " + oBNum; mPaint.getTextBounds(txt, 0, txt.length(), mBound); //計算弧度的中心點 point = new float[2]; point[0] = (float)(radius * Math.cos(Math.PI * (Math.abs(90 - oBArc / 2)) / 180)); point[1] = (float)(radius * Math.sin(Math.PI * (Math.abs(90 - oBArc / 2)) / 180)); /** * 右側第一個弧度,無論為何值,它都不會在左半球,出現折線,所以它有四種情況 * 1,弧度小於160時,它的中心線在90度以上,只所以沒有取180,是因為中間要留出20度,給直線,所以它有一個向上的折線。 * 2,弧度小於等於200時,因為是一個else語句,所以它的中心點范圍是80--100,是一條直線。 * 3,弧度小於340時,因為是一個else語句,所以它的中心點范圍是 100-170,是一條向下的折線。 * 4,弧度小於360時,因為是一個else語句,所以它的中心點范圍是 170-180,它是一條向下垂直的線 */ //畫弧上的線 drawLine(canvas, oBArc / 2, radius, 1); canvas.drawText(txt, txtEndX - mBound.width() - adjustDist / 2, txtBeginY - adjustDist / 2, mPaint); //畫線後的橢圓 txtNumPre = getProValText(oBpre); mPaint.getTextBounds(txtNumPre, 0, txtNumPre.length(), mBound); mPaint.setStyle(Paint.Style.FILL); canvas.drawRoundRect(txtEndX + 10, txtBeginY - mBound.height() / 2 - adjustDist/2, txtEndX + adjustDist/2 + mBound.width() + 30, txtBeginY - mBound.height() / 2 + mBound.height() + adjustDist/2, 15, 15, mPaint); mPaint.setColor(Color.parseColor("#ffffff")); canvas.drawText(txtNumPre, txtEndX + adjustDist / 2 + adjustDist / 2, txtBeginY + mBound.height() / 2, mPaint); } } /** * 流出中單 * @param canvas 畫板 * @param radius 中心半徑 * @param oBArc 流出大單弧度 * @param oMArc 流出中單弧度 * @param oMpre 流出中單百分比 */ public void DrawOM(Canvas canvas,float radius,float oBArc,float oMArc,float oMpre) { if(oMNum>0) { mPaint.setColor(oMColor); mPaint.setTextSize(TextSize); String txt = "中單 " + oMNum; mPaint.getTextBounds(txt, 0, txt.length(), mBound); point = new float[2]; point[0] = (float)(radius * Math.cos(Math.PI * (Math.abs(90 - (oMArc / 2 + oBArc))) / 180)); point[1] = (float)(radius * Math.sin(Math.PI * (Math.abs(90 - (oMArc/2 + oBArc)))/180)); /** * 右側第二個弧度,所以它有七種情況,它的情況與第一個弧度有關,所以它的弧度值要與第一個弧度進行相加來處理 * 第一個弧度加上本身弧度的一半,可以得到中心點的位置,根據中心的位置進行判斷其位置 * 1,弧度中心點小於80時,它的中心線在90度以上,只所以沒有取180,是因為中間要留出20度,給直線,所以它有一個向上的折線。 * 2,弧度中心點小於等於100時,因為是一個else語句,所以它的中心點范圍是80--100,是一條直線。 * 3,弧度中心點小於170時,因為是一個else語句,所以它的中心點范圍是 100-170,是一條向下的折線。 * 4,弧度中心點小於180時,因為是一個else語句,所以它的中心點范圍是 170-180,它是一條向下垂直的線 * 5,弧度中心點小於260時,因為是一個else語句,所以它會在左邊生成一個向下拆的線 * 6,弧度中心點小於280時,因為是一個else語句,它會在左邊中間的位置生下一條直線 * 7,弧度中心點於小360時,因為是一個else語句,它會在左邊上部,生成一個向上有折線的線 */ float oMCenterArc = oBArc + oMArc/2; //畫弧上的線 drawLine(canvas, oMCenterArc, radius, 1); //畫出線上數據與後面橢圓型的百分比 drawRect(canvas, txt, oMpre, oMCenterArc,1); } } /** * 流出小單 * @param canvas 畫板 * @param radius 中心半徑 * @param oBMArc 流出大單和中單弧度和 * @param oSArc 流出小單弧度 * @param oSpre 流出小單百分比 */ public void DrawOS(Canvas canvas,float radius,float oBMArc,float oSArc,float oSpre) { if(oSNum>0) { mPaint.setColor(oSColor); mPaint.setTextSize(TextSize); String txt = "小單 " + oSNum; mPaint.getTextBounds(txt, 0, txt.length(), mBound); point = new float[2]; point[0] = (float)(radius * Math.cos(Math.PI * (Math.abs(90 - (oSArc / 2 + oBMArc))) / 180)); point[1] = (float)(radius * Math.sin(Math.PI * (Math.abs(90 - (oSArc/2 + oBMArc)))/180)); float oMCenterArc = oBMArc + oSArc/2; //畫弧上的線 drawLine(canvas,oMCenterArc,radius,1); drawRect(canvas,txt,oSpre,oMCenterArc,1); } } /** * 流入小單 * @param canvas 畫板 * @param radius 中心半徑 * @param oBMSArc 流出大單,中單,小單弧度和 * @param iSArc 流入小單弧度 * @param iSpre 流入小單百分比 */ public void DrawIS(Canvas canvas,float radius,float oBMSArc,float iSArc,float iSpre) { if(iSNum>0) { mPaint.setColor(iSColor); mPaint.setTextSize(TextSize); String txt = "小單 " + iSNum; mPaint.getTextBounds(txt, 0, txt.length(), mBound); point = new float[2]; point[0] = (float)(radius * Math.cos(Math.PI * (Math.abs(90 - (iSArc / 2 + oBMSArc))) / 180)); point[1] = (float)(radius * Math.sin(Math.PI * (Math.abs(90 - (iSArc / 2 + oBMSArc))) / 180)); float oMCenterArc = oBMSArc + iSArc/2; //畫弧上的線 drawLine(canvas,oMCenterArc,radius,2); //畫出線上數據與後面橢圓型的百分比 drawRect(canvas,txt,iSpre,oMCenterArc,2); } } /** * 流入中單 * @param canvas 畫板 * @param radius 中心半徑 * @param oBMSiMArc 流出大單,中單,小單,流入小單弧度和 * @param iMArc 流入中單弧度 * @param iMpre 流入中單百分比 */ public void DrawIM(Canvas canvas,float radius,float oBMSiMArc,float iMArc,float iMpre) { if(iMNum>0) { mPaint.setColor(iSColor); mPaint.setTextSize(TextSize); String txt = "中單 " + iMNum; mPaint.getTextBounds(txt, 0, txt.length(), mBound); point = new float[2]; point[0] = (float)(radius * Math.cos(Math.PI * (Math.abs(90 - (iMArc / 2 + oBMSiMArc))) / 180)); point[1] = (float)(radius * Math.sin(Math.PI * (Math.abs(90 - (iMArc/2 + oBMSiMArc)))/180)); float oMCenterArc = oBMSiMArc + iMArc/2; //畫弧上的線 drawLine(canvas, oMCenterArc, radius,2); //畫出線上數據與後面橢圓型的百分比 drawRect(canvas,txt,iMpre,oMCenterArc,2); } } /** * 流入大單 * @param canvas 畫板 * @param radius 中心半徑 * @param oBMSiSMArc 流出大單,中單,小單,流入小單,中單弧度和 * @param iBArc 流入大單弧度 * @param iBpre 流入大單百分比 */ public void DrawIB(Canvas canvas,float radius,float oBMSiSMArc,float iBArc,float iBpre) { if(iMNum>0) { mPaint.setColor(iSColor); mPaint.setTextSize(TextSize); String txt = "大單 " + iBNum; mPaint.getTextBounds(txt, 0, txt.length(), mBound); point = new float[2]; point[0] = (float)(radius * Math.cos(Math.PI * (Math.abs(90 - (iBArc / 2 + oBMSiSMArc))) / 180)); point[1] = (float)(radius * Math.sin(Math.PI * (Math.abs(90 - (iBArc/2 + oBMSiSMArc)))/180)); float oMCenterArc = oBMSiSMArc + iBArc/2; //畫弧上的線 drawLine(canvas,oMCenterArc,radius,2); //畫出線上數據與後面橢圓型的百分比 drawRect(canvas,txt,iBpre,oMCenterArc,2); } } /** * 根據弧度值,來畫出弧度中心點伸出的線 * @param canvas 畫板 * @param sumArc 弧度之和 * @param radius 中心半徑 * @param flag 標識位,1:左側流出單 2:右側注入單 */ public void drawLine(Canvas canvas,float sumArc,float radius,int flag) { if(sumArc <= 80) { draw80(canvas); }else if(sumArc <=100) { draw100(canvas,sumArc); }else if(sumArc <=170){ draw170(canvas); }else if(sumArc <=190) { draw180(canvas,radius,flag); }else if(sumArc <=260) { draw260(canvas); } else if(sumArc <=290) { draw280(canvas); }else { draw360(canvas); } } /** * 畫出弧度中心點小於80弧度的上面的線與值 * 這裡的弧度中心點小於80,是它前面的所有弧度加上它本身的總度數的一半,如果是第一個弧,則為其本身的一半,此處畫出的是左側80度以下,帶有向上折線的兩根線 * @param canvas 畫板 */ public void draw80(Canvas canvas) { txtBeginX = getWidth()/2 + point[0] + 40; txtBeginY = getHeight()/2 - point[1] - 20; canvas.drawLine(getWidth()/2 + point[0], getHeight()/2 - point[1], txtBeginX, txtBeginY,mPaint); txtEndX = txtBeginX + mBound.width() + 20; canvas.drawLine(txtBeginX,txtBeginY, txtEndX,txtBeginY,mPaint); } /** * 畫出弧度中心點大於等於80小於等於100弧度上面的線與值 * 這裡的弧度中心點大於等於80小於等於100,是它前面的所有弧度加上它本身的總度數的一半,如果是第一個弧,則為其本身的一半,此處畫出的是左側80-100度之間,一根直線 * @param canvas 畫板 * @param sumArc 當前總弧度,當弧度大於90度時,其Y軸起始點應該向下移 */ public void draw100(Canvas canvas,float sumArc) { txtBeginX = getWidth() / 2 + point[0]; if(sumArc>90) { txtBeginY = getHeight() / 2 + point[1]; }else { txtBeginY = getHeight() / 2 - point[1]; } txtEndX = txtBeginX + mBound.width() + adjustDist; canvas.drawLine(txtBeginX, txtBeginY, txtEndX, txtBeginY, mPaint); } /** * 畫出弧度中心點大於100小於170弧度上面的線與值 * 這裡的弧度中心點大於100小於170,是它前面的所有弧度加上它本身的總度數的一半,如果是第一個弧,則為其本身的一半,此處畫出的是左側100-170度之間,帶有向下折線的兩根線 * @param canvas 畫板 */ public void draw170(Canvas canvas) { txtBeginX = getWidth()/2 + point[0] + adjustDist*2; txtBeginY = getHeight()/2 + point[1] + adjustDist; canvas.drawLine(getWidth()/2 + point[0], getHeight()/2 + point[1], txtBeginX, txtBeginY, mPaint); txtEndX = txtBeginX + mBound.width() + adjustDist; canvas.drawLine(txtBeginX, txtBeginY, txtEndX, txtBeginY, mPaint); } /** * 畫出弧度中心點大於170小於190弧度上面的線與值 * 這裡的弧度中心點大於170小於190,是它前面的所有弧度加上它本身的總度數的一半,如果是第一個弧,則為其本身的一半,此處畫出的是左側170-190度之間,帶有垂直向下折線的兩根線 * @param canvas 畫板 * @param radius 半徑 * @param flag 標識位 1:右側流出量 2:左側流入量 */ public void draw180(Canvas canvas,float radius,int flag) { txtBeginX = getWidth() / 2 + point[0]; txtBeginY = getHeight() / 2 + point[1] + adjustDist; canvas.drawLine(getWidth() / 2 + point[0], getHeight() / 2 + point[1], txtBeginX, txtBeginY, mPaint); //此處加一個判斷,主要是當在最下面畫線的時候,流出向右畫線,流入向左畫線 if(flag==1) { txtEndX = txtBeginX + radius / 2 + mBound.width() + adjustDist; }else{ txtEndX = txtBeginX - radius / 2 - mBound.width() - adjustDist; } canvas.drawLine(txtBeginX, txtBeginY, txtEndX, txtBeginY, mPaint); } /** * 畫出弧度中心點大於190,小於260弧度上面的線與值 * 這裡的弧度中心點大於190小於260,是它前面的所有弧度加上它本身的總度數的一半,此處畫出的是左側190-260度之間,右邊帶有垂直向下折線的兩根線 * @param canvas 畫板 */ public void draw260(Canvas canvas) { txtBeginX = getWidth() / 2 + point[0] - 40; txtBeginY = getHeight() / 2 + point[1] + 20; canvas.drawLine(getWidth() / 2 + point[0], getHeight() / 2 + point[1], txtBeginX, txtBeginY, mPaint); txtEndX = txtBeginX - mBound.width() - 20; canvas.drawLine(txtBeginX, txtBeginY, txtEndX, txtBeginY, mPaint); } /** * 畫出弧度中心點大於260,小於280弧度上面的線與值 * 這裡的弧度中心點大於260小於280,是它前面的所有弧度加上它本身的總度數的一半,此處畫出的是左側260-280度之間,右邊的一根直線 * @param canvas 畫板 */ public void draw280(Canvas canvas) { txtBeginX = getWidth() / 2 + point[0]; txtBeginY = getHeight() / 2 + point[1]; txtEndX = txtBeginX - mBound.width() - 20; canvas.drawLine(txtBeginX, txtBeginY, txtEndX, txtBeginY, mPaint); } /** * 畫出弧度中心點大於280,小於360弧度上面的線與值 * 這裡的弧度中心點大於280小於360,是它前面的所有弧度加上它本身的總度數的一半,此處畫出的是左側280-360度之間,右邊向上折的兩根直線 * @param canvas 畫板 */ public void draw360(Canvas canvas) { txtBeginX = getWidth()/2 + point[0] - 40; txtBeginY = getHeight()/2 + point[1] - 20; canvas.drawLine(getWidth() / 2 + point[0], getHeight() / 2 + point[1], txtBeginX, txtBeginY, mPaint); txtEndX = txtBeginX - mBound.width() - 20; canvas.drawLine(txtBeginX, txtBeginY, txtEndX, txtBeginY, mPaint); } /** * 畫線上的文字與後面橢圓型的百分比 * @param canvas 畫板 * @param txt 線上文字 * @param iBpre 百分比 * @param oMCenterArc 弧度數 * @param flag 標識位 1: 右邊流出量 2: 左邊流入量 */ public void drawRect(Canvas canvas,String txt,float iBpre,float oMCenterArc,int flag) { if(oMCenterArc >=80 && oMCenterArc <=100) { draw100Rect(canvas,txt,iBpre); } else if(oMCenterArc<=190) { draw190Rect(canvas,txt,iBpre,flag,oMCenterArc); }else { drawOtherRect(canvas,txt,iBpre); } } /** * 處了右側第一個弧度外。當前弧度的一半加上之前弧度的和,在80-100之間,畫出線上文字與之後的百分比 * @param canvas 畫板 * @param txt 線上文字 * @param oMpre 百分比 */ public void draw100Rect(Canvas canvas,String txt,float oMpre) { canvas.drawText(txt, txtBeginX + 10, txtBeginY - 10, mPaint); //畫線後的橢圓 txtNumPre = getProValText(oMpre); mPaint.getTextBounds(txtNumPre, 0, txtNumPre.length(), mBound); mPaint.setStyle(Paint.Style.FILL); canvas.drawRoundRect(txtEndX + 10, txtBeginY - mBound.height() / 2 - 10, txtEndX + 10 + mBound.width() + 30, txtBeginY - mBound.height() / 2 + mBound.height() + 10, 15, 15, mPaint); mPaint.setColor(Color.parseColor("#ffffff")); canvas.drawText(txtNumPre, txtEndX + 10 + 10, txtBeginY + mBound.height() / 2, mPaint); } /** * 處了右側第一個弧度外。當前弧度的一半加上之前弧度的和,在小於等於190,並且不包括80-100的數據,畫出線上文字與之後的百分比 * @param canvas 畫板 * @param txt 線上文字 * @param oMpre 百分比 * @param flag 標識位 1:右側流出 2:左側流入 * @param oMArc 弧度之和 */ public void draw190Rect(Canvas canvas,String txt,float oMpre,int flag,float oMArc) { //左側的流入三個弧度,如果在正下方,則特殊處理 if(flag==2 && (oMArc>=170 && oMArc <=190)) { canvas.drawText(txt, txtEndX + 20, txtBeginY - 10, mPaint); //畫線後的橢圓 txtNumPre = getProValText(oMpre); mPaint.getTextBounds(txtNumPre, 0, txtNumPre.length(), mBound); mPaint.setStyle(Paint.Style.FILL); canvas.drawRoundRect(txtEndX - 10 - 10 - mBound.width() - 10 , txtBeginY - mBound.height() / 2 - 10, txtEndX - 10, txtBeginY - mBound.height() / 2 + mBound.height() + 10, 15, 15, mPaint); mPaint.setColor(Color.parseColor("#ffffff")); canvas.drawText(txtNumPre, txtEndX - 10 - 10 - mBound.width(), txtBeginY + mBound.height() / 2, mPaint); }else { canvas.drawText(txt, txtEndX - mBound.width() - 20, txtBeginY - 10, mPaint); //畫線後的橢圓 txtNumPre = getProValText(oMpre); mPaint.getTextBounds(txtNumPre, 0, txtNumPre.length(), mBound); mPaint.setStyle(Paint.Style.FILL); canvas.drawRoundRect(txtEndX + 10, txtBeginY - mBound.height() / 2 - 10, txtEndX + 20 + mBound.width() + 20, txtBeginY - mBound.height() / 2 + mBound.height() + 10, 15, 15, mPaint); mPaint.setColor(Color.parseColor("#ffffff")); canvas.drawText(txtNumPre, txtEndX + 20, txtBeginY + mBound.height() / 2, mPaint); } } /** * 處了右側第一個弧度外。當前弧度的一半加上之前弧度的和,在大於190,畫出線上文字與之後的百分比 * @param canvas 畫板 * @param txt 線上文字 * @param oMpre 百分比 */ public void drawOtherRect(Canvas canvas,String txt,float oMpre) { canvas.drawText(txt, txtEndX + 10, txtBeginY - 10, mPaint); //畫線後的橢圓 txtNumPre = getProValText(oMpre); mPaint.getTextBounds(txtNumPre, 0, txtNumPre.length(), mBound); mPaint.setStyle(Paint.Style.FILL); canvas.drawRoundRect(txtEndX - 10 - mBound.width() - 30, txtBeginY - mBound.height() / 2 - 10, txtEndX - 10, txtBeginY - mBound.height() / 2 + mBound.height() + 10, 15, 15, mPaint); mPaint.setColor(Color.parseColor("#ffffff")); canvas.drawText(txtNumPre, txtEndX - 10 - mBound.width() - 30 + 10, txtBeginY + mBound.height() / 2, mPaint); } /** * 格式化顯示的百分比 * @param proValue 傳入的數值一般是0.1234這種格式的 * @return 返回一個小數點後一位的百分比字符串 */ private String getProValText(float proValue) { DecimalFormat format = new DecimalFormat("#0.0"); return format.format(proValue * 100) + "%"; } public void setNum(float oBNum,float oMNum, float oSNum,float iBNum,float iMNum,float iSNum) { this.oBNum = oBNum; this.oMNum = oMNum; this.oSNum = oSNum; this.iBNum = iBNum; this.iMNum = iMNum; this.iSNum = iSNum; //計算總數 sum = oBNum + oMNum + oSNum + iBNum + iMNum + iSNum; //計算六個值的百分比 oBpre = oBNum / sum; oMpre = oMNum / sum; oSpre = oSNum / sum; iBpre = iBNum / sum; iMpre = iMNum / sum; iSpre = iSNum / sum; //計算六個值所占圓的弧度數 oBArc = oBpre * 360; oMArc = oMpre * 360; oSArc = oSpre * 360; iBArc = iBpre * 360; iMArc = iMpre * 360; iSArc = iSpre * 360; mOBArc = 1; mOMArc = 1; mOSArc = 1; mISArc = 1; mIMArc = 1; mIBArc = 1; postInvalidate(); } }
//自定義屬性名,定義公共屬性 //自定義控件的主題樣式
AnimationCirPre.java 添加了動畫效果。
本文主要是對Handler和消息循環的實現原理進行源碼分析,如果不熟悉Handler可以參見博文《詳解Android中Handler的使用方法》,裡面對Android為何
android-async-http開源項目可以是我們輕松的獲取網絡數據或者向服務器發送數據,使用起來非常簡單,關於android-async-http開源項目的介紹內容
本文實例為大家分享了Android仿微信發表說說、心情功能,供大家參考,具體內容如下既能實現拍照,選圖庫,多圖案上傳的案例,目前好多App都有類似微信朋友圈的功能,能過發
一、Xamarin for VS的版本簡介下面是Xamarin for VS發布的版本簡介:……更早的版本(略)2015年11月發布:Xamarin for VS 4.0