Android菜鳥練習第四課 自定義PieView實現餅圖效果

 第一部分 自定義PieView

public class PieChartView extends View {
    //定義多種顏色供使用
    private int arcColos[] = new int[]{getResources().getColor(R.color.gold), getResources().getColor(R.color.greenyellow)
            , getResources().getColor(R.color.lightgreen), getResources().getColor(R.color.dodgerblue)
            , getResources().getColor(R.color.freshgreen), getResources().getColor(R.color.lightskyblue)};
    private final static String TAG = "PieChartView";

    private List<PieMember> data = null;

    //圓心位置
    private int centerX, centerY = 0;
    //整個餅圖的半徑
    private float radius = 200;
    //中間原型半徑
    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.white));

        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);
        }
        if (this.centerX == 0) {
            this.centerX = getWidth() / 2;
        }
        if (this.centerY == 0) {
            this.centerY = ((getHeight() - lableHeight) / 2)+30;
        }
        this.fontSize = -scalaFonts((int) (hollowRadius / this.pieName.length() * 0.6f) * 2);

        //繪製整個餅圖的底部背景圓
        this.bgPaint.setColor(getResources().getColor(R.color.white));
        this.bgPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        canvas.drawCircle(centerX, centerY, radius, bgPaint);

        //畫百分比圓弧
        this.drawArc(canvas);
        canvas.restore();
    }

    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*10);
            citePaint.setStrokeWidth(1);
            citePaint.setColor(getResources().getColor(R.color.theme_main_blue));
            //繪製餅圖中的文字
            canvas.drawTextOnPath(member.getText(), path, 20, 0, citePaint);
            //在餅圖的下方繪製文字
//            citePaint.setTextSize(fontSize*5);
//            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;
        }

    }
}
第二部分 color文件

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#3F51B5</color>
    <color name="colorPrimaryDark">#303F9F</color>
    <color name="colorAccent">#FF4081</color>

    //餅圖顏色
    <color name="gold">#FFD700</color>
    <!-- 金 -->
    <color name="greenyellow">#ADFF2F</color>
    <!-- 赭 -->
    <color name="lightgreen">#90EE90</color>
    <!-- 亮綠 -->
    <color name="dodgerblue">#1E90FF</color>
    <!-- 閃藍 -->
    <color name="freshgreen">#C4EAA2</color>
    <!-- 清新綠 -->
    <color name="lightskyblue">#87CEFA</color>
    <!-- 亮天藍 -->
    <color name="white">#ffffff</color>
    <!-- 白色 -->
    <color name="theme_main_blue">#ff20bdea</color>
    <color name="black_overlay">#66000000</color>

</resources>

第三部分 Activity中
public class MainActivity extends Activity {
    private PieChartView mPieView;
    private ArrayList<PieChartView.PieMember> datas = new ArrayList<PieChartView.PieMember>();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mPieView = (PieChartView) findViewById(R.id.piechart);

        PieChartView.PieMember member1 = new PieChartView.PieMember();
        member1.setColor(Color.parseColor("#fcb333"));
        member1.setNumber(15);
        member1.setText("美女");

        PieChartView.PieMember member2 = new PieChartView.PieMember();
        member2.setColor(Color.parseColor("#fedd95"));
        member2.setNumber(35);
        member2.setText("帥哥");

        PieChartView.PieMember member3 = new PieChartView.PieMember();
        member3.setColor(Color.parseColor("#cccccc"));
        member3.setNumber(50);
        member3.setText("中性人");

        datas.add(member1);
        datas.add(member2);
        datas.add(member3);

        mPieView.setData(datas);

    }

}

第四部分 佈局部分

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >

   <com.example.liying.viewpager.PieChartView
       android:layout_width="300dp"
       android:layout_height="300dp"
       android:layout_centerHorizontal="true"
       android:id="@+id/piechart"
       android:layout_marginTop="50dp"
       />

</RelativeLayout>

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章