最近專案裡碰上了餅圖,順便整理了下幾種Android餅圖,以作參考
阿新 • • 發佈:2019-01-24
第一種:自定義一個piechart,親自來畫一個餅圖,歸根結底還是參照老外的思路,但是還是有自己的一點想法在裡面,先上程式碼:
import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import java.util.List; public class PieChartView extends View { private int arcColos[] = new int[]{getResources().getColor(R.color.gold),Color.BLUE, getResources().getColor(R.color.coral),Color.RED, getResources().getColor(R.color.hotpink), Color.GREEN, getResources().getColor(R.color.mintcream),getResources().getColor(R.color.orange)}; private final static String TAG = "PieChartView"; private List<PieMember> data = null; //圓心位置 private int centerX, centerY = 0; //整個餅圖的半徑 private float radius = 0; //中間原型半徑 private float hollowRadius = 0; //餅圖邊距 private float margin = 0; //餅圖名稱 private String pieName = "得分比例"; //lable高度 private int lableHeight = 80; private float fontSize = 0; private Paint bgPaint = null; private Paint arcPaint = null; private Paint textPaint = null; public PieChartView(Context context) { super(context); this.init(); } public PieChartView(Context context, AttributeSet attrs) { super(context, attrs); this.init(); } public PieChartView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); this.init(); } public void setPieName(String pieName) { this.pieName = pieName; postInvalidate(); } private void init() { this.bgPaint = new Paint(); bgPaint.setAntiAlias(true); this.bgPaint.setColor(getResources().getColor(R.color.theme_main_blue)); this.bgPaint.setStyle(Paint.Style.FILL_AND_STROKE); this.arcPaint = new Paint(); this.arcPaint.setAntiAlias(true); this.arcPaint.setStyle(Paint.Style.FILL_AND_STROKE); this.textPaint = new Paint(); this.textPaint.setColor(getResources().getColor(R.color.black_overlay)); this.textPaint.setAntiAlias(true);//去除鋸齒 this.textPaint.setFilterBitmap(true);//對點陣圖進行濾波處理 } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //canvas.drawColor(getResources().getColor(R.color.pageBgColor)); canvas.drawColor(getResources().getColor(android.R.color.transparent));//設定背景透明 if (margin == 0) { margin = getWidth() * 0.05f; } if (radius == 0) { if ((getHeight() - lableHeight) < getWidth()) { radius = (getHeight() - lableHeight - (margin * 2)) / 2; } else { radius = (getWidth() - (margin * 2)) / 2; } } else if ((radius * 2) > (getWidth() - (margin * 2))) { radius = (getWidth() - (margin * 2)) / 2; } else if ((radius * 2 + lableHeight) > (getHeight() - (margin * 2))) { ViewGroup.LayoutParams params = getLayoutParams(); params.height = (int) (radius * 2d + lableHeight + (margin * 2d)); setLayoutParams(params); } if (hollowRadius == 0) { hollowRadius = (int) (radius * 0.5f); } if (this.centerX == 0) { this.centerX = getWidth() / 2; } if (this.centerY == 0) { this.centerY = (getHeight() - lableHeight) / 2; } this.fontSize = scalaFonts((int) (hollowRadius / this.pieName.length() * 0.6f) * 2); //畫最下一層的圓圈 this.bgPaint.setColor(getResources().getColor(R.color.theme_main_blue)); this.bgPaint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.drawCircle(centerX, centerY, radius, bgPaint); //畫百分比圓弧 this.drawArc(canvas); this.bgPaint.setColor(getResources().getColor(R.color.pageBgColor)); this.bgPaint.setStyle(Paint.Style.FILL_AND_STROKE); canvas.drawCircle(centerX, centerY, hollowRadius, bgPaint); this.bgPaint.setStyle(Paint.Style.STROKE); this.bgPaint.setColor(getResources().getColor(R.color.black_overlay)); canvas.drawCircle(centerX, centerY, hollowRadius * 0.9f, bgPaint); drawText(canvas); canvas.restore(); } public void drawText(Canvas canvas) { int x = getWidth(); int y = getHeight() - lableHeight; this.textPaint.setTextSize(this.fontSize); float tX = (x - getFontlength(this.textPaint, this.pieName)) / 2; float tY = (y - getFontHeight(this.textPaint)) / 2 + getFontLeading(this.textPaint); canvas.drawText(this.pieName, tX, tY, this.textPaint); } public void drawArc(Canvas canvas) { RectF rect = new RectF(); rect.left = centerX - radius; rect.top = centerY - radius; rect.right = centerX + radius; rect.bottom = centerY + radius; RectF rectText = new RectF(); rectText.left = centerX - (radius - (radius * 0.4f)); rectText.top = centerY - (radius - (radius * 0.4f)); rectText.right = centerX + (radius - (radius * 0.4f)); rectText.bottom = centerY + (radius - (radius * 0.4f)); if (this.data == null || this.data.isEmpty()) { Log.w(TAG, "沒有可以繪製的資料"); arcPaint.setColor(arcColos[0]); canvas.drawArc(rect, //弧線所使用的矩形區域大小 0, //開始角度 60, //掃過的角度 true, //是否使用中心 arcPaint); return; } int total = 0;//總數 for (PieMember member : data) { total += member.getNumber(); } float angle = 0f; int i = 0; for (int pointer = 0; pointer < data.size(); pointer++) { PieMember member = data.get(pointer); if (member.getColor() == 0) { if (i >= arcColos.length) { i = 0; } member.setColor(arcColos[i++]); } float d = 360f * ((float) member.getNumber() / (float) total); arcPaint.setColor(member.getColor()); canvas.drawArc(rect, angle, d, true, arcPaint); //根據進度畫圓弧 Path path = new Path(); path.addArc(rectText, angle, d); Paint citePaint = new Paint(); citePaint.setTextSize(fontSize * 0.6F); citePaint.setStrokeWidth(1); citePaint.setColor(getResources().getColor(R.color.black)); canvas.drawTextOnPath(member.getText(), path, 50, 0, citePaint); //在底部寫文字,此處我們不需要 float x = getWidth() / data.size() * pointer + margin; float y = getHeight() - margin; float h = getFontHeight(this.textPaint) * 0.6f; canvas.drawText(member.getText() + ":" + member.getNumber(), x + h + (h * 0.3f), y, citePaint); RectF r = new RectF(x, y - h, x + h, y); canvas.drawRect(r, arcPaint); angle += d; } } /** * 根據螢幕係數比例獲取文字大小 * * @return */ private static float scalaFonts(int size) { //暫未實現 return size; } /** * @return 返回指定筆和指定字串的長度 */ public static float getFontlength(Paint paint, String str) { return paint.measureText(str); } /** * @return 返回指定筆的文字高度 */ public static float getFontHeight(Paint paint) { Paint.FontMetrics fm = paint.getFontMetrics(); return fm.descent - fm.ascent; } /** * @return 返回指定筆離文字頂部的基準距離 */ public static float getFontLeading(Paint paint) { Paint.FontMetrics fm = paint.getFontMetrics(); return fm.leading - fm.ascent; } public void setData(List<PieMember> data) { this.data = data; postInvalidate(); } public static class PieMember { private String text = ""; private int number = 0; private int color = 0; public void augment(int n) { this.number += n; } public String getText() { return text; } public void setText(String text) { this.text = text; } public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public int getColor() { return color; } public void setColor(int color) { this.color = color; } } }
protected void initData() { hashMap = new HashMap<>(); for (int i = 0; i < 6;i++){ hashMap.put("科"+ (i+1), i + 5); } float total = 35.0f; pieChart.setPieName("錯題分佈"); pieChart.setData(initPie(hashMap, total)); } private List<PieChartView.PieMember> initPie(HashMap<String,Integer> hashMap,float total) { List<PieChartView.PieMember> data = new ArrayList<>(); Iterator<Map.Entry<String, Integer>> iterator = hashMap.entrySet().iterator(); while(iterator.hasNext()){ PieChartView.PieMember member = new PieChartView.PieMember(); Map.Entry<String, Integer> entry = iterator.next(); String key = entry.getKey(); int val = entry.getValue(); member.setNumber(val); member.setText(key +"錯"+val); // member.setColor(Color.parseColor(Constant.pieColors[index])); //index++; data.add(member); } return data; }