自定義View實現Android圓形進度條

jopen 9年前發布 | 1K 次閱讀 Java Android

通過繼承Android的View類,重寫onDraw方法。

    import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.SeekBar;

public class CycleView extends View {  

    Paint mPaint;  
    int progress = 30;  
    int start_degree = -90;  

    public CycleView(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        InitResources(context, attrs);  

    }  

    int background_int;  
    int progress_int;  
    float layout_width_float;  
    int textColor_int;  
    float textSize_float;  
    int max_int;  
    Drawable thumb_double;  
    int thumbSize_int;  

    private void InitResources(Context context, AttributeSet attrs) {  
        TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.windows);  

        background_int = mTypedArray.getColor(R.styleable.windows_background, 0xFF87cfe8);  
        progress_int = mTypedArray.getColor(R.styleable.windows_progressDrawable, 0xFFabd800);  
        layout_width_float = mTypedArray.getDimension(R.styleable.windows_layout_width, 7);  
        textColor_int = mTypedArray.getColor(R.styleable.windows_textColor, 0xFFada1de);  
        textSize_float = mTypedArray.getDimension(R.styleable.windows_textSize, 50);  
        max_int = mTypedArray.getInt(R.styleable.windows_max, 100);  
        progress = mTypedArray.getInt(R.styleable.windows_progress, 20);  
        thumb_double = mTypedArray.getDrawable(R.styleable.windows_thumb);  
        thumbSize_int = mTypedArray.getInt(R.styleable.windows_thumbSize, 30);  
        mTypedArray.recycle();  

        if (thumb_double == null) {  
            Bitmap bitmap = Bitmap.createBitmap(thumbSize_int, thumbSize_int, Bitmap.Config.ARGB_8888);  
            // 圖片畫片  
            Canvas cas = new Canvas(bitmap);  
            Paint paint = new Paint();  
            paint.setStyle(Style.FILL);  
            paint.setColor(0xFF68ba32);  
            int center = thumbSize_int / 2;  
            int radius = center - 4;  
            cas.drawCircle(center, center, radius, paint);  
            thumb_double = new BitmapDrawable(getResources(), bitmap);  
        }  

        mPaint = new Paint();  
    }  

    @Override  
    protected void onDraw(Canvas canvas) {  
        super.onDraw(canvas);  
        drawProgressView(canvas);  
    }  

    private void drawProgressView(Canvas canvas) {  
        InitOval(canvas);  
        drawBackground(canvas);  
        drawProgress(canvas);  
        drawProgressText(canvas);  
    }  

    RectF oval;  

    private void InitOval(Canvas canvas) {  
        int center = getWidth() / 2;  
        int radius = (int) (center  - thumbSize_int / 2);  
        // 畫布中央減去半徑就是左上角  
        int left_top = center - radius;  
        // 畫布中央加上半徑就是右下角  
        int right_bottom = center + radius;  

        if (oval == null) {  
            oval = new RectF(left_top, left_top, right_bottom, right_bottom);  
        }  
    }  

    /** 
     * 繪制進度文字 
     *  
     * @param canvas 
     */  
    private void drawProgressText(Canvas canvas) {  

        mPaint.setTextSize(textSize_float);  
        mPaint.setColor(textColor_int);  
        mPaint.setStrokeWidth(2);  
        mPaint.setStyle(Style.FILL);  
        String progresstext = progress + "%";  
        float text_left = (getWidth() - mPaint.measureText(progresstext)) / 2;  
        FontMetrics fontMetrics = mPaint.getFontMetrics();  
        // 繪制文字是底部對齊  
        float text_top = (float) ((getHeight() / 2 + Math.ceil(fontMetrics.descent - fontMetrics.ascent) / 2));  
        canvas.drawText(progresstext, text_left, text_top, mPaint);  
    }  

    private void drawProgress(Canvas canvas) {  
        // 設置進度  
        mPaint.setColor(progress_int);  
        mPaint.setStrokeWidth(layout_width_float);  
        float seek = 0;  
        if (max_int > 0) {  
            seek = (float) progress / max_int * 360;  
        }  
        canvas.drawArc(oval, start_degree, seek, false, mPaint);  

        canvas.save();  
        int center = getWidth() / 2;  
        int radius = (int) (center - thumbSize_int / 2);  

        double cycle_round = (seek + start_degree) * Math.PI / 180;  
        float x = (float) (Math.cos(cycle_round) * (radius) + center - thumbSize_int / 2);  
        float y = (float) (Math.sin(cycle_round) * (radius) + center - thumbSize_int / 2);  
        thumb_double.setBounds(0, 0, thumbSize_int, thumbSize_int);  
        canvas.translate(x, y);  
        thumb_double.draw(canvas);  
        canvas.restore();  
    }  

    private void drawBackground(Canvas canvas) {  

        mPaint.setStrokeWidth(layout_width_float);  
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setAntiAlias(true);  
        // 設置背景  
        mPaint.setColor(background_int);  
        canvas.drawArc(oval, start_degree, 360, false, mPaint);  

    }  

    /** 
     * 查看Seekbar源碼 
     *  
     * @param progress 
     */  
    public synchronized void setProgress(int progress) {  
        if (progress > max_int) {  
            progress = max_int;  
        }  
        this.progress = progress;  
        postInvalidate();  
    }  

    public int getProgress() {  
        return this.progress;  
    }  

    @Override  
    protected void onDetachedFromWindow() {  
        super.onDetachedFromWindow();  
        if (thumb_double != null) {  
            thumb_double.setCallback(null);  
            thumb_double = null;  
        }  
    }  

}  </pre> 


然后是XML,因為要用到自定義屬性

    <?xml version="1.0" encoding="utf-8"?>
<resources>

    <!-- 參考Seekbar -->  
    <declare-styleable name="windows">  

        <!-- 背景顏色 -->  
        <attr name="background" format="color" />  
        <!-- 進度顏色 -->  
        <attr name="progressDrawable" format="color" />  
        <!-- 寬度 -->  
        <attr name="layout_width" format="dimension" />  
        <!-- 字體顏色 -->  
        <attr name="textColor" format="color" />  
        <!-- 字體大小 -->  
        <attr name="textSize" format="dimension" />  
        <!-- 最大進度 -->  
        <attr name="max" format="integer" />  
        <!-- 進度 -->  
        <attr name="progress" format="integer" />  
        <!-- 進度點 -->  
        <attr name="thumb" format="reference" />  
        <!-- 進度點寬高 -->  
        <attr name="thumbSize" format="integer" />  
    </declare-styleable>  

</resources>  </pre> 


最后是在代碼里的用法

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

    <com.windows.canvas.CycleView  
        android:layout_centerInParent="true"  
        xmlns:windows="http://schemas.android.com/apk/res/com.finals.canvas"  
        android:layout_width="150dp"  
        android:layout_height="150dp" />  

</RelativeLayout>  </pre> 


 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!