1. 程式人生 > >自定義View---實現半圓環形進度條

自定義View---實現半圓環形進度條

圖表控制元件很多,這個多少能跟圖表控制元件扯上邊吧。
廢話不多說,看圖:
這裡寫圖片描述

上面可以看到效果,支援各種自定義,支援點選

這裡沒有用到 自定義屬性。有興趣的可以自己設定下。直接看程式碼

    public class CircleBar extends View {
    private static final String TAG = "CircleBar";

    private RectF mColorWheelRectangle = new RectF();//圓圈的矩形範圍
    private Paint mDefaultWheelPaint;////繪製底部灰色圓圈的畫筆
private Paint mColorWheelPaint;//繪製藍色扇形的畫筆 private Paint textPaint;//中間數值文字的畫筆 private Paint textDesPaint;//描述文字的畫筆 private float mColorWheelRadius; private float circleStrokeWidth;//圓圈的線條粗細 private float pressExtraStrokeWidth; private int mTextColor = getResources().getColor(R.color.blue);//預設文字顏色
private int mWheelColor = getResources().getColor(R.color.blue);//預設圓環顏色 private String mText; private String mTextDes;//文字的描述 private int mTextDesSize;//描述文字的大小 private int mCount;//為了做動畫 private float mSweepAnglePer;//扇形弧度百分比 private float mSweepAngle;//扇形弧度 private int mTextSize;//文字大小
private int mDistance;// 上下文字的距離 BarAnimation anim;//動畫 private int TIME = 1000;//時間 public CircleBar(Context context) { super(context); init(null, 0); } public CircleBar(Context context, AttributeSet attrs) { super(context, attrs); init(attrs, 0); } public CircleBar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(attrs, defStyle); } private void init(AttributeSet attrs, int defStyle) { //初始化一些值 circleStrokeWidth = dip2px(getContext(), 10); pressExtraStrokeWidth = dip2px(getContext(), 2); mTextSize = dip2px(getContext(), 30); mTextDesSize = dip2px(getContext(), 15); mDistance = dip2px(getContext(), 30);//文字距離 //外圓環的畫筆 mColorWheelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mColorWheelPaint.setColor(mWheelColor); mColorWheelPaint.setStyle(Style.STROKE); mColorWheelPaint.setStrokeWidth(circleStrokeWidth);//圓圈的線條粗細 mColorWheelPaint.setStrokeCap(Paint.Cap.ROUND);//開啟顯示邊緣為圓形 //預設圓的畫筆 mDefaultWheelPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mDefaultWheelPaint.setColor(getResources().getColor(R.color.gray)); mDefaultWheelPaint.setStyle(Style.STROKE); mDefaultWheelPaint.setStrokeWidth(circleStrokeWidth);//圓圈的線條粗細 mDefaultWheelPaint.setStrokeCap(Paint.Cap.ROUND);//開啟顯示邊緣為圓形 //數值的畫筆 textPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); textPaint.setColor(mTextColor); textPaint.setStyle(Style.FILL_AND_STROKE); textPaint.setTextAlign(Align.LEFT); textPaint.setTextSize(mTextSize); //描述文字的畫筆 textDesPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.LINEAR_TEXT_FLAG); textDesPaint.setColor(getResources().getColor(R.color.gray)); textDesPaint.setStyle(Style.FILL_AND_STROKE); textDesPaint.setTextSize(mTextDesSize); textDesPaint.setTextAlign(Align.LEFT); mText = "0"; mTextDes = "本次考試"; mSweepAngle = 0; anim = new BarAnimation(); anim.setDuration(TIME); } @Override protected void onDraw(Canvas canvas) { canvas.drawArc(mColorWheelRectangle, -180, 180, false, mDefaultWheelPaint);//畫外接的圓環 canvas.drawArc(mColorWheelRectangle, -180, mSweepAnglePer, false, mColorWheelPaint);//畫圓環 Rect bounds = new Rect(); String textstr = mCount + ""; textPaint.getTextBounds(textstr, 0, textstr.length(), bounds); textDesPaint.getTextBounds(mTextDes, 0, mTextDes.length(), bounds); // drawText各個屬性的意思(文字,x座標,y座標,畫筆) canvas.drawText( textstr + "", (mColorWheelRectangle.centerX()) - (textPaint.measureText(textstr) / 2), mColorWheelRectangle.centerY() + bounds.height() / 2 - 50, textPaint); canvas.drawText(mTextDes, (mColorWheelRectangle.centerX()) - (textDesPaint.measureText(mTextDes) / 2), mColorWheelRectangle.centerY() + bounds.height() / 2 - 50 - mDistance , textDesPaint); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); int width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); int min = Math.min(width, height); setMeasuredDimension(min, min); mColorWheelRadius = min - circleStrokeWidth - pressExtraStrokeWidth; mColorWheelRectangle.set(circleStrokeWidth + pressExtraStrokeWidth, circleStrokeWidth + pressExtraStrokeWidth, mColorWheelRadius, mColorWheelRadius); } @Override public void setPressed(boolean pressed) { Toast.makeText(getContext(), mText, Toast.LENGTH_SHORT).show(); } public void startCustomAnimation() { this.startAnimation(anim); } public void setText(String text) { mText = text; this.startAnimation(anim); } public void setDesText(String text) { mTextDes = text; this.startAnimation(anim); } public void setTextColor(int color) { mTextColor = color; textPaint.setColor(mTextColor); } public void setSweepAngle(float sweepAngle) { mSweepAngle = sweepAngle; } public void setWheelColor(int color) { this.mColorWheelPaint.setColor(color); } public class BarAnimation extends Animation { /** * Initializes expand collapse animation, has two types, collapse (1) and expand (0). * 1 will collapse view and set to gone */ public BarAnimation() { } // * 動畫類利用了applyTransformation引數中的interpolatedTime引數(從0到1)的變化特點, // * 實現了該View的某個屬性隨時間改變而改變。原理是在每次系統呼叫animation的applyTransformation()方法時, // * 改變mSweepAnglePer,mCount的值, // * 然後呼叫postInvalidate()不停的繪製view。 @Override protected void applyTransformation(float interpolatedTime, Transformation t) { super.applyTransformation(interpolatedTime, t); //mSweepAnglePer,mCount這兩個屬性只是動畫過程中要用到的臨時屬性, //mText和mSweepAngle才是動畫結束之後表示扇形弧度和中間數值的真實值。 if (interpolatedTime < 1.0f) { mSweepAnglePer = interpolatedTime * mSweepAngle; mCount = (int) (interpolatedTime * Float.parseFloat(mText)); } else { mSweepAnglePer = mSweepAngle; mCount = Integer.parseInt(mText); } postInvalidate(); } } public static int dip2px(Context context, float dipValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dipValue * scale + 0.5f); } }

註釋非常清楚了。就不詳細說明了。直接在在佈局中使用。因為沒有自定義屬性,大家懂的。

這裡新增點選事件,通常繼承自view都有onClick和oLongClick事件的。這裡加進去就好

    //監聽器類介面

    public static abstract interface  OnClickListener{
        public abstract void onClick(); //單擊事件處理介面
    }

    OnClickListener   listener=null;   //監聽器類物件

    //實現這個View的監聽器

    public void setOnClickListener(OnClickListener  listener){

        this.listener = listener;   //引用監聽器類物件,在這裡可以使用監聽器類的物件

    }