Android 自定義View - 餅圖


  最近有看到一個自定義等分圓的View,自己嘗試做了一個類似的,效果圖如下圖(1)所示:

圖(1)

  實現方法:自定義View-ColorCircle,需要的知道的值有圓的半徑,等分個數以及扇形顏色。

    /**
     * 定義幾種顏色
     */
    private static int COLOR[] = {Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW, Color.BLACK};
    /**
     * 圓等分默認數目
     */
    private static int DIV_SIZE = 3;

    private Paint mPaint;
   /** 
   * 圓默認半徑
   */
private static final int DEFAULT_RADIUS = 200; private int mRadius = DEFAULT_RADIUS;
public ColorCircle(Context context) { this(context, null); } public ColorCircle(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public ColorCircle(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mPaint = new Paint(); mPaint.setStyle(Paint.Style.FILL); }

  在onMeasure中我們需要根據widthMeasureSpec & heightMeasureSpec重新計算ColorCircle View的尺寸以及圓的半徑(因為默認圓的直徑可能會大於View的高 or 寬)。

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int width;
        int height;

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = mRadius * 2 + getPaddingLeft() + getPaddingRight();
            if (widthMode == MeasureSpec.AT_MOST) {
                width = Math.min(width, widthSize);
            }
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = mRadius * 2 + getPaddingTop() + getPaddingBottom();
            if (heightMode == MeasureSpec.AT_MOST) {
                height = Math.min(width, heightSize);
            }
        }

        setMeasuredDimension(width, height);
        mRadius = (int) (Math.min(width - getPaddingLeft() - getPaddingRight(),
                height - getPaddingTop() - getPaddingBottom()) * 1.0f / 2);
    }

  最后在onDraw里通過canvas.drawArc()來繪制扇形。

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//平移Canvas到屏幕中心,之后的繪制以中心點為初始點 canvas.translate((getWidth()
+ getPaddingLeft() - getPaddingRight()) / 2,
             (getHeight() + getPaddingTop() - getPaddingBottom()) / 2);
//定義一個RectF對象,表示扇形繪制區域 RectF oval = new RectF(-mRadius, -mRadius, mRadius, mRadius);
float firstAngle = 0.0f; float divideAngle = (360 * 1.0f) / DIV_SIZE;//根據DIV_SIZE來算每個扇形的角度 for (int i=0; i<DIV_SIZE; i++) { mPaint.setColor(COLOR[i]); canvas.drawArc(oval, (firstAngle + i * divideAngle), divideAngle, true, mPaint); } }

    public void setDivSize(int size){
        DIV_SIZE = size;
        invalidate();
    }

    public int getDivSize(){
        DIV_SIZE = size;
    }
 

  最后還預留了一個setDivSize()接口,方便自定義ColorCircle View動態變化扇形數目。我這里是通過Seekbar來動態切換DIV_SIZE。

    mColorCircle = (ColorCircle)findViewById(R.id.color_circle);
    mSeekBar = (SeekBar)findViewById(R.id.seek_bar);
    mSeekBar.setMax(4);//因為顏色數目原因,這里seekBar的最大值設置為了4。
int pro = mColorCircle.getSize(); mSeekBar.setProgress(
pro); mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mColorCircle.setDivSize(progress + 1); } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onStopTrackingTouch(SeekBar seekBar) { } });

  效果圖如下:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM