自定义View实现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;
		}
	}

}
然后是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>

最后是在代码里的用法
<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.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>
然后是效果图


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值