女神镇楼
这次实在上一篇圆形进度条的基础上在进度的末尾处增加一个图片。效果如下:
解释一下:绿色背景是我们控件所占的空间大小。我想要的效果就是:在绘制的过程中,图片的中心始终跟着进度走。且进度的圆环末端中心点就是图片的中心点。理论图如下:
以上就是原理图,下面直接上代码:
/**
* Created by Administrator on 2017/12/18.
* 圆形进度条
* 可增加进度图片
*/
public class CircleProgressView extends android.support.v7.widget.AppCompatTextView {
/**
* 圆环默认宽度
*/
private float defaultStrokeWidth = 10;
/**
* 进度值0~100
*/
private int mProgress;
/**
* 起始角度0~360
* -90为正上方
* 0为3点位置
*/
private int fromAngle = 0;//
// private int textSize = 14;
// private int textColor;//默认666666;
// private String text = "张三";
private int mRadius;//圆弧半径 不包括圆环厚度
private boolean isCapRound = true;//进度是开头和结尾否是圆形的
private Paint mPaint;
private Paint mBgPaint;
private Paint mBitmapPaint;
RectF ovl;//圆环内环绘制的区域
private boolean isProgressing = false;//是否正在绘制进度 防止线程多重绘制
Bitmap mBitmap;
public CircleProgressView(Context context) {
this(context, null);
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mBgPaint = new Paint();
mBgPaint.setAntiAlias(true);
mBgPaint.setDither(true);
mBgPaint.setStyle(Paint.Style.STROKE);
mBitmapPaint = new Paint();
mBitmapPaint.setAntiAlias(true);
mBitmapPaint.setDither(true);
mBitmapPaint.setStyle(Paint.Style.FILL);
int strokeColor = Color.parseColor("#ff0000");
int strokeBgColor = Color.parseColor("#f6f6f6");
if (attrs != null){
TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.circleProgressView);
strokeBgColor = array.getColor(R.styleable.circleProgressView_strokeBgColor, Color.parseColor("#f6f6f6"));
strokeColor = array.getColor(R.styleable.circleProgressView_strokeColor, Color.parseColor("#ff0000"));
defaultStrokeWidth = (int) array.getDimension(R.styleable.circleProgressView_strokeWidth, 10);
mRadius = (int) array.getDimension(R.styleable.circleProgressView_radius, 10);
mProgress = array.getInteger(R.styleable.circleProgressView_progress, 0);
fromAngle = array.getInteger(R.styleable.circleProgressView_fromAngle, 0);
isCapRound = array.getBoolean(R.styleable.circleProgressView_isCapRound, true);
if (fromAngle < 0){
fromAngle = 0;
}else if (fromAngle > 360){
fromAngle = -90 + fromAngle%360;
}
array.recycle();
}
if (isCapRound){
mPaint.setStrokeCap(Paint.Cap.ROUND);
}
mPaint.setStrokeWidth(defaultStrokeWidth);
mPaint.setColor(strokeColor);
mBgPaint.setStrokeWidth(defaultStrokeWidth);
mBgPaint.setColor(strokeBgColor);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_marke);
if (mBitmap != null){
if (mBitmap.getWidth() > defaultStrokeWidth && mBitmap.getHeight() > defaultStrokeWidth){
setPadding((int)(mBitmap.getWidth() - defaultStrokeWidth)/2, (int)(mBitmap.getHeight() - defaultStrokeWidth)/2, (int)(mBitmap.getWidth() - defaultStrokeWidth)/2, (int)(mBitmap.getHeight() - defaultStrokeWidth)/2);
}else if (mBitmap.getWidth() > defaultStrokeWidth && mBitmap.getHeight() <= defaultStrokeWidth){
setPadding((int)(mBitmap.getWidth() - defaultStrokeWidth)/2, 0, (int)(mBitmap.getWidth() - defaultStrokeWidth)/2, 0);
}else if (mBitmap.getWidth() <= defaultStrokeWidth && mBitmap.getHeight() > defaultStrokeWidth){
setPadding(0, (int)(mBitmap.getHeight() - defaultStrokeWidth)/2, 0, (int)(mBitmap.getHeight() - defaultStrokeWidth)/2);
}
// ovl = new RectF(getPaddingLeft() + 0 + defaultStrokeWidth/2, getPaddingTop() + 0 + defaultStrokeWidth/2, 2 * mRadius - + defaultStrokeWidth/2 - getPaddingRight(), 2 * mRadius - + defaultStrokeWidth/2 - getPaddingBottom());
}else{
// ovl = new RectF(0 + defaultStrokeWidth/2, 0 + defaultStrokeWidth/2, 2 * mRadius - + defaultStrokeWidth/2, 2 * mRadius - + defaultStrokeWidth/2);
}
ovl = new RectF(getPaddingLeft() + defaultStrokeWidth/2, getPaddingTop() + defaultStrokeWidth/2, getPaddingLeft() + 2 * mRadius + defaultStrokeWidth * 3/2, getPaddingTop() + 2 * mRadius + defaultStrokeWidth*3/2);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// int width = MeasureSpec.getSize(widthMeasureSpec);
// int widthMode = MeasureSpec.getMode(widthMeasureSpec);
// int height = MeasureSpec.getSize(heightMeasureSpec);
// int heightMode = MeasureSpec.getMode(heightMeasureSpec);
setMeasuredDimension((int)(getPaddingLeft() + getPaddingRight() + 2 *(mRadius + defaultStrokeWidth)), (int)(getPaddingTop() + getPaddingBottom() + 2 *(mRadius + defaultStrokeWidth)));
// setMeasuredDimension(getDefaultSize(width, widthMeasureSpec), getDefaultSize(height, heightMeasureSpec));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// ovl = new RectF(0 + defaultStrokeWidth/2, 0 + defaultStrokeWidth/2, getMeasuredWidth() - + defaultStrokeWidth/2, getMeasuredHeight() - + defaultStrokeWidth/2);
canvas.drawArc(ovl, fromAngle - 90, 360, false, mBgPaint);
canvas.drawArc(ovl, fromAngle - 90, 360 * mProgress/100, false, mPaint);
// canvas.drawText(text, getWidth()/2, getHeight()/
canvas.drawBitmap(mBitmap, (float) (mRadius + defaultStrokeWidth/2 + (mRadius + defaultStrokeWidth/2) *Math.sin( 2*PI/360*360 * mProgress/100) - mBitmap.getWidth()/2 + getPaddingLeft() + defaultStrokeWidth/2),
(float)(mRadius + defaultStrokeWidth/2 - (mRadius + defaultStrokeWidth/2) *Math.cos( 2*PI/360*360 * mProgress/100) - mBitmap.getHeight()/2 + getPaddingTop() + defaultStrokeWidth/2), mBitmapPaint);
}
public void setProgress(int progress){
if (progress <= 0){
progress = 0;
mProgress = 0;
postInvalidate();
}else if (progress > 100){
progress = 100;
}
//解决多个线程同时修改界面的问题
if (isProgressing)
isProgressing = false;
final int finalProgress = progress;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
isProgressing = true;
new Thread() {
@Override
public void run() {
super.run();
//防止上一个线程的影响
for (int i = 0; i < finalProgress; i++) {
mProgress = i;
postInvalidate();
try {
Thread.sleep(30);
} catch (InterruptedException e) {
e.printStackTrace();
}
if (!isProgressing) {
break;
}
}
isProgressing = false;
}
}.start();
}
}, 50);
}
}
用法跟圆形进度条一样,不清楚可以看上一篇。多了两条属性
<attr name="resId" format="integer"/> <attr name="radius" format="dimension"/>
That is all。