android自定義View&自定義ViewGroup(上)
阿新 • • 發佈:2019-01-25
核心程式碼(程式碼中有詳細註釋):
public class CakeView extends View { //裝載的餅狀圓資料 private List<CakeBean> beanList; //畫圓的矩形 private RectF mRectF; //右邊的小矩形 private RectF iRectF; private Paint mPaint; private int mRWidth, mRHeight; private float rotateDegree;//每個圓弧的起始角度 private float sumValue = 0;//所有值的和 private float diameter;//圓的直徑 private float textY;//繪製文字的Y座標 private float mRectHeight = 40;//矩形高度 private float mRectWidth = 80;//矩形寬度 private float mMargin = 40;//矩形和圓的距離 private Context mContext; public CakeView(Context context) { //CakeView cakeView=new CakeView(context); // 在程式碼中new CakeView()會呼叫這個建構函式 this(context, null); } public CakeView(Context context, AttributeSet attrs) { //InflateLayoutManager時會呼叫這個建構函式 this(context, attrs, 0); } public CakeView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; init(); } private void init() { beanList = new ArrayList<>(); mRectF = new RectF(); mPaint = new Paint(); mPaint.setAntiAlias(true); mPaint.setDither(true); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //MeasureSpec封裝了父View傳遞給子View的佈局要求 //寬度測量模式 int wMode = MeasureSpec.getMode(widthMeasureSpec); //寬度測量值 int wSize = MeasureSpec.getSize(widthMeasureSpec); //高度測量模式 int hMode = MeasureSpec.getMode(heightMeasureSpec); //高度測量值 int hSize = MeasureSpec.getSize(heightMeasureSpec); switch (wMode) { case MeasureSpec.EXACTLY: //相當於match_parent或者一個具體值 mRWidth = wSize; break; case MeasureSpec.AT_MOST: // 相當於wrap_content ,需要手動測量大小,這裡先寫死大小 mRWidth = (int) DpUtil.dp2px(mContext, 400f); break; case MeasureSpec.UNSPECIFIED: //很少會用到 break; default: break; } switch (hMode) { case MeasureSpec.EXACTLY: //相當於match_parent或者一個具體值 mRHeight = hSize; break; case MeasureSpec.AT_MOST: // 相當於wrap_content ,需要手動測量大小,這裡先寫死大小 mRHeight = (int) DpUtil.dp2px(mContext, 200f); break; case MeasureSpec.UNSPECIFIED: //很少會用到 break; default: break; } //儲存測量好的寬和高 setMeasuredDimension(wSize, hSize); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); diameter = Math.min(mRWidth, mRHeight); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //設定圓形繪製的範圍 mRectF.set(0, 0, diameter, diameter); //畫布中心X座標向右移動(控制元件寬度-圓直徑)之差的八分之一的距離 //畫布中心Y座標向下移動(控制元件寬度-圓直徑)之差的二分之一的距離 canvas.translate((mRWidth - diameter) / 8, (mRHeight - diameter) / 2); if (beanList.size() > 0 && Float.compare(sumValue, 0.0f) != 0) { for (int i = 0; i < beanList.size(); i++) { CakeBean bean = beanList.get(i); //畫圓弧 mPaint.setColor(bean.mColor); canvas.drawArc(mRectF, rotateDegree, bean.degree, true, mPaint); rotateDegree += bean.degree; //畫矩形和文字 drawRectAndText(canvas, bean); } } } private void drawRectAndText(Canvas canvas, CakeBean bean) { iRectF = new RectF(); //設定畫矩形的範圍 float left = diameter + mMargin; float right = diameter + mMargin + mRectWidth; float bottom = textY + mRectHeight; iRectF.set(left, textY, right, bottom); canvas.drawRect(iRectF, mPaint); //設定顏色 mPaint.setColor(Color.BLACK); //設定文字大小 mPaint.setTextSize(30); //畫文字 canvas.drawText(bean.name + "(" + new DecimalFormat(".00").format(bean.value / sumValue * 100) + "%)", right + 10, textY + 30, mPaint); textY += mRectHeight; } /** * 餅狀圖新增資料 * * @param beans CakeBean資料 */ public void setData(List<CakeBean> beans) { if (beans == null || beans.size() <= 0) return; for (int i = 0; i < beans.size(); i++) { CakeBean bean = beans.get(i); sumValue += bean.value; } for (int i = 0; i < beans.size(); i++) { CakeBean bean = beans.get(i); bean.degree = bean.value / sumValue * 360; beanList.add(bean); } invalidate(); } /** * @param startDegree 設定起始角度 */ public void setStartDegree(float startDegree) { this.rotateDegree = startDegree; invalidate(); }}
自定義View的使用先到這裡,自定義ViewGroup接下篇