网上有很多弧形或者圆形的ProgressBar和SeekBar。前几天无意中发现一个弧形的ProgressBar觉得挺不错的,就下载来看看源码。
运行他的Demo的时候发现几个问题,并且有些问题在issue里面也有人提出了,但是作者一直没有回复,我把问题修复之后加上了Seek的功能,让它能当做SeekBar用。
不能通过XML配置控件的大小,源码里面写死了,写成占屏幕的百分比。
有几个属性的颜色值设置无效。比如默认的弧形背景色
放大缩小控件之后对应的字体没有相应的调整大小
我们从最下面带刻度带提示的效果图入手
####我们呢先分析原作者的代码:
package com.shinelw.colorarcprogressbar;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.PaintFlagsDrawFilter;import android.graphics.RectF;import android.graphics.SweepGradient;import android.util.AttributeSet;import android.util.DisplayMetrics;import android.view.View;import android.view.WindowManager;/**
* colorful arc progress bar
* Created by shinelw on 12/4/15.
*/public class ColorArcProgressBar extends View{
private int mWidth; private int mHeight; //直径
private int diameter = 500; private RectF bgRect; //圆心
private float centerX; private float centerY; private Paint allArcPaint; private Paint progressPaint; private Paint vTextPaint; private Paint hintPaint; private Paint degreePaint; private Paint curSpeedPaint; private float startAngle = 135; private float sweepAngle = 270; private float currentAngle = 0; private float lastAngle; private int[] colors = {Color.GREEN, Color.YELLOW, Color.RED, Color.RED}; private ValueAnimator progressAnimator; private float maxValues = 60; private float curValues = 0; private int bgArcWidth = dipToPx(2); private int progressWidth = dipToPx(10); private int textSize = dipToPx(80); private int hintSize = dipToPx(22); private int curSpeedSize = dipToPx(13); private int aniSpeed = 1000; private int longdegree = dipToPx(13); private int shortdegree = dipToPx(5); private final int DEGREE_PROGRESS_DISTANCE = dipToPx(8); private String hintColor = "#676767"; private String longDegreeColor = "#d2d2d2"; private String shortDegreeColor = "#adadad"; private String bgArcColor = "#111111"; private boolean isShowCurrentSpeed = true; private String hintString = "Km/h"; // sweepAngle / maxValues 的值
private float k; public ColorArcProgressBar(Context context) { super(context);
initView();
} public ColorArcProgressBar(Context context, AttributeSet attrs) { super(context, attrs);
initView();
} public ColorArcProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr);
initView();
} @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE; int height= 2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE;
setMeasuredDimension(width, height);
} private void initView() {
diameter = 3 * getScreenWidth() / 5; //弧形的矩阵区域
bgRect = new RectF();
bgRect.top = longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE;
bgRect.left = longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE;
bgRect.right = diameter + (longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE);
bgRect.bottom = diameter + (longdegree + progressWidth/2 + DEGREE_PROGRESS_DISTANCE); //圆心
centerX = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE)/2;
centerY = (2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE)/2; //外部刻度线
degreePaint = new Paint();
degreePaint.setColor(Color.parseColor(longDegreeColor)); //整个弧形
allArcPaint = new Paint();
allArcPaint.setAntiAlias(true);
allArcPaint.setStyle(Paint.Style.STROKE);
allArcPaint.setStrokeWidth(bgArcWidth);
allArcPaint.setColor(Color.parseColor(bgArcColor));
allArcPaint.setStrokeCap(Paint.Cap.ROUND); //当前进度的弧形
progressPaint = new Paint();
progressPaint.setAntiAlias(true);
progressPaint.setStyle(Paint.Style.STROKE);
progressPaint.setStrokeCap(Paint.Cap.ROUND);
progressPaint.setStrokeWidth(progressWidth);
progressPaint.setColor(Color.GREEN); //当前速度显示文字
vTextPaint = new Paint();
vTextPaint.setTextSize(textSize);
vTextPaint.setColor(Color.WHITE);
vTextPaint.setTextAlign(Paint.Align.CENTER); //显示“km/h”文字
hintPaint = new Paint();
hintPaint.setTextSize(hintSize);
hintPaint.setColor(Color.parseColor(hintColor));
hintPaint.setTextAlign(Paint.Align.CENTER); //显示“km/h”文字
curSpeedPaint = new Paint();
curSpeedPaint.setTextSize(curSpeedSize);
curSpeedPaint.setColor(Color.parseColor(hintColor));
curSpeedPaint.setTextAlign(Paint.Align.CENTER);
} @Override
protected void onDraw(Canvas canvas) { //抗锯齿
canvas.setDrawFilter(new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG|Paint.FILTER_BITMAP_FLAG)); //画刻度线
for (int i = 0; i 15 && i maxValues) {
currentValues = maxValues;
} if (currentValues = 0 ? 1 : -1));
} /**
* 得到屏幕宽度
* @return
*/
private int getScreenWidth() {
WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(displayMetrics); return displayMetrics.widthPixels;
} public void setIsShowCurrentSpeed(boolean isShowCurrentSpeed) { this.isShowCurrentSpeed = isShowCurrentSpeed;
} /**
* 初始加载页面时设置加载动画
*/
public void setDefaultWithAnimator() {
setAnimation(sweepAngle, currentAngle, 2000);
}
}123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
从以上代码可以看出:
在initView 的时候设置了弧形的直径diameter = 3 * getScreenWidth() / 5;也就是弧形的直径是根据屏幕的大小定的。
我们再看OnMeasure方法
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = 2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE; int height= 2 * longdegree + progressWidth + diameter + 2 * DEGREE_PROGRESS_DISTANCE;
setMeasuredDimension(width, height);
}
所以我们知道:不管你怎么设置控件的宽高,都没有效果。这是第一个问题
设置某些颜色值无效的问题:
颜色值的设置是通常作用于画笔上,我们先看看几个画笔:
private Paint allArcPaint;//背景弧形的画笔(圆弧) private Paint progressPaint;//进度画笔(当前速度) private Paint vTextPaint;//内容文字画笔(80) private Paint hintPaint;//单位文字画笔(km/h) private Paint degreePaint;//刻度画笔(刻度条) private Paint curSpeedPaint;//标题文字画笔(当前速度)
这些画笔的颜色值在initView的时候初始化,但是颜色值并没有在initConfig的时候取出属性值并且配置,所以这是导致设置颜色无效的原因
注意:给画笔设置的颜色值必须带有透明度,不然会自动带上全透明效果。看不到任何信息
调整控件大小的时候圆弧内的文字没有做出大小和位置的调整
在源代码中,initView的时候就已经设置TextSize了,而initView是在实例化的时候调用的,这时候控件的大小都还没有确定,所以需要把和大小相关的值都放到OnSizeChange中,或者在OnMeasure中获取控件的实际大小之后再初始化这些值
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{ super.onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
Log.v("ColorArcProgressBar", "onSizeChanged: mWidth:" + mWidth + " mHeight:" + mHeight);
diameter = (int) (Math.min(mWidth, mHeight) - 2 * (longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2));
Log.v("ColorArcProgressBar", "onSizeChanged: diameter:" + diameter); //弧形的矩阵区域
bgRect = new RectF();
bgRect.top = longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2;
bgRect.left = longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2;
bgRect.right = diameter + (longDegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE);
bgRect.bottom = diameter + (longDegree + progressWidth / 2 + DEGREE_PROGRESS_DISTANCE);
Log.v("ColorArcProgressBar", "initView: " + diameter); //圆心
centerX = (2 * (longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2) + diameter) / 2;
centerY = (2 * (longDegree + DEGREE_PROGRESS_DISTANCE + progressWidth / 2) + diameter) / 2;
sweepGradient = new SweepGradient(centerX, centerY, colors, null);
mTouchInvalidateRadius = Math.max(mWidth, mHeight) / 2 - longDegree - DEGREE_PROGRESS_DISTANCE - progressWidth * 2; if(isAutoTextSize)
{
textSize = (float) (diameter * 0.3);
hintSize = (float) (diameter * 0.1);
curSpeedSize = (float) (diameter * 0.1);
vTextPaint.setTextSize(textSize);
hintPaint.setTextSize(hintSize);
curSpeedPaint.setTextSize(curSpeedSize);
}
}
通过在OnSizeChange中初始化这些动态的尺寸,就解决了文字缩放的问题。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/1868/viewspace-2806089/ ,如需转载,请注明出处,否则将追究法律责任。