android自定义等级评分圆形进度条

一、测试截图

二、实现原理

 

 

package com.freedomanlib;

import java.util.Timer;
import java.util.TimerTask;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * @name GradeProgressBar
 * @Descripation 自定义等级评分圆形进度条,用于设备数据统计页面一键评分<br>
 *               1、初始化边界宽度、中心坐标和外环、内环半径,各种画笔。<br>
 *               2、默认最大进度为100,目标进度由用户来指定。<br>
 *               3、锁定一个内圆环为可点击区域。 <br>
 *               4、点击组件时,调用start()方法启动计时器,重绘界面。<br>
 * @author Freedoman
 * @date 2014-10-29
 * @version 1.0
 */
public class GradeProgressBar extends View {

	private static final String TAG = "CircleProgressBar";

	/**
	 * 边界宽度、中心坐标和外环、内环半径
	 */
	private float boundsWidth;
	private float centerPoint;
	private float overRadius;
	private float radius;

	/**
	 * 最大进度、当前进度、是否显示进度文本
	 */
	private float maxProgress = 100;
	private float targetProgress;
	private int curProgress;

	/**
	 * 几种画笔
	 */
	private Paint overRoundPaint;
	private Paint roundPaint;
	private Paint progressRoundPaint;
	private Paint progressTextPaint;
	private Paint textPaint;

	/**
	 * 可点击区域的边界
	 */
	private float clickBoundsLow;
	private float clickBoundsHigh;

	private onProgressChangedListener listener;

	public GradeProgressBar(Context context) {
		this(context, null);
	}

	public GradeProgressBar(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public GradeProgressBar(Context context, AttributeSet attrs,
			int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		this.initialize();
	}

	/**
	 * 初始化
	 */
	private void initialize() {

		curProgress = 0;
		int whiteColor = Color.rgb(0xF0, 0xF0, 0xF0);

		// 外环画笔
		overRoundPaint = new Paint();
		overRoundPaint.setColor(whiteColor);
		overRoundPaint.setStyle(Paint.Style.STROKE);
		overRoundPaint.setStrokeWidth(8);
		overRoundPaint.setAntiAlias(true);

		// 内环画笔
		roundPaint = new Paint();
		roundPaint.setColor(Color.GRAY);
		roundPaint.setStrokeWidth(30);
		roundPaint.setStyle(Paint.Style.STROKE);
		roundPaint.setAntiAlias(true);

		// 进度环画笔(除颜色外同于内环)
		progressRoundPaint = new Paint();
		progressRoundPaint.setColor(Color.rgb(0xFF, 0x92, 0x24));
		progressRoundPaint.setStrokeWidth(20);
		progressRoundPaint.setStyle(Paint.Style.STROKE);
		roundPaint.setAntiAlias(true);

		// 进度文本画笔
		progressTextPaint = new Paint();
		progressTextPaint.setColor(whiteColor);
		progressTextPaint.setStyle(Paint.Style.STROKE);
		progressTextPaint.setStrokeWidth(0);
		progressTextPaint.setTextSize(80);
		progressTextPaint.setTypeface(Typeface.DEFAULT_BOLD);

		// 文本画笔
		textPaint = new Paint();
		textPaint.setColor(whiteColor);
		textPaint.setStyle(Paint.Style.STROKE);
		textPaint.setStrokeWidth(0);
		textPaint.setTextSize(40);
		textPaint.setTypeface(Typeface.DEFAULT_BOLD);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		// 取当前布局的最短边作为边框的长度
		float width = getWidth();
		float heigh = getHeight();
		boundsWidth = width <= heigh ? width : heigh;

		// 中心点
		centerPoint = boundsWidth / 2;
		// 外环半径
		overRadius = centerPoint - 20;
		// 内环半径
		radius = overRadius - 25;

		// 内环所在区域(正方形)锁定为可点击区域
		clickBoundsLow = centerPoint - radius;
		clickBoundsHigh = centerPoint + radius;
	}

	/**
	 * 启动进度动画
	 */
	public void start() {
		curProgress = 0;
		if (targetProgress == 0) {
			targetProgress = 66;
		}
		final Timer timer = new Timer();
		TimerTask timerTask = new TimerTask() {
			@Override
			public void run() {
				curProgress++;
				if (curProgress == targetProgress) {
					timer.cancel();
				}
				postInvalidate();
			}
		};
		timer.schedule(timerTask, 0, 20);
	}

	@SuppressLint("DrawAllocation")
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		// 外环
		canvas.drawCircle(centerPoint, centerPoint, overRadius, overRoundPaint);
		// 内环
		canvas.drawCircle(centerPoint, centerPoint, radius, roundPaint);

		// 进度环
		RectF oval = new RectF(centerPoint - radius, centerPoint - radius,
				centerPoint + radius, centerPoint + radius);
		float curArc = 360 * curProgress / maxProgress;
		canvas.drawArc(oval, 0, curArc, false, progressRoundPaint);

		// 环中心进度文本
		int curPercent = (int) ((curProgress / maxProgress) * 100);
		float textWidth = progressTextPaint.measureText(curPercent + "%");
		canvas.drawText(curPercent + "%", centerPoint - textWidth / 2,
				centerPoint, progressTextPaint);

		if (curPercent == 0) {
			// 暂未评级
			float w = textPaint.measureText("暂未评级");
			canvas.drawText("暂未评级", centerPoint - w / 2, centerPoint + 40,
					textPaint);
		} else if (curPercent < targetProgress) {
			// 评级中...
			float w = textPaint.measureText("评级中...");
			canvas.drawText("评级中...", centerPoint - w / 2, centerPoint + 40,
					textPaint);
		} else if (curPercent == targetProgress) {
			// 评级完成
			float w = textPaint.measureText("评级完成");
			canvas.drawText("评级完成", centerPoint - w / 2, centerPoint + 40,
					textPaint);
		}

		// 对外传递数据
		if (listener != null) {
			listener.progressChanged(GradeProgressBar.this, curProgress);
		}
	}

	public synchronized float getMaxProgress() {
		return maxProgress;
	}

	/**
	 * 设置进度的最大值
	 * 
	 * @param max
	 */
	public synchronized void setMaxProgress(float max) {
		if (max < 0) {
			throw new IllegalArgumentException("max not less than 0");
		}
		this.maxProgress = max;
	}

	/**
	 * 获取进度.需要同步
	 * 
	 * @return
	 */
	public synchronized float getProgress() {
		return targetProgress;
	}

	/**
	 * 设置进度,此为线程安全控件,由于考虑多线的问题,需要同步 刷新界面调用postInvalidate()能在非UI线程刷新
	 * 
	 * @param progress
	 */
	public synchronized void setProgress(float progress) {
		if (progress < 0) {
			throw new IllegalArgumentException("progress not less than 0");
		}
		if (progress > maxProgress) {
			progress = maxProgress;
		}
		if (progress <= maxProgress) {
			this.targetProgress = progress;
		}
	}

	public void setOnProgressChangedListener(onProgressChangedListener listener) {
		if (listener == null) {
			this.listener = listener;
		}
	}

	/**
	 * 点击评分区域,进行评分
	 * 
	 * @param event
	 * @return
	 */
	@Override
	public boolean onTouchEvent(MotionEvent event) {

		float x = event.getX();
		float y = event.getY();

		if (x > clickBoundsLow && x < clickBoundsHigh && y > clickBoundsLow
				&& y < clickBoundsHigh) {
			start();
		}
		return super.onTouchEvent(event);
	}

	/**
	 * @name onProgressChangedListener
	 * @Descripation 对外接口,提供当前旋转进度<br>
	 *               1、<br>
	 *               2、<br>
	 * @author Freedoman
	 * @date 2014-10-29
	 * @version 1.0
	 */
	public interface onProgressChangedListener {
		public void progressChanged(GradeProgressBar circleProgressBar,
				int curProgress);
	}
}

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值