写一个等级条view效果如下:
前言:对于熟悉自定义view的同学来说,这个效果实在是太简单了。自己写的时候发现,在写之前一定要事先把各个测量点,绘制的点计算方法想好,不然还是要调试一番才能完善,当然我这个肯定还不够完善,勉强看的过去了。
用到知识点:
1、view测量
2、shader
3、属性动画
重点:等级划分的时候,每个等级有一个开始点和结束点,比如0-50,50-200;在这个效果中,每个等级的宽度是一样的,所以比如100的时候,它的宽度就是,一分宽度,加(100-50)/(200-50)*一个等级宽度,有了这个思维之后其他都是小问题了。
1、测量高度,宽度不用测量了,因为你定义view的时候肯定会告诉我一个固定的宽度吧(mathparent也是一个精确宽度)
这个如果要写自定义view需要先定义字体大小,图片大小,进度条宽度等等,为了方便直接用变量写死,想要支撑自定义属性的时候直接取出来赋值就可以了。这里偷懒跳过。。。
首先拿到图片的宽高和字体的高度
public void getLevelImgWH() {
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), levelimgs_gray[0], opts);
this.levelImgWidth = opts.outWidth;
this.levelImgHeight = opts.outHeight;
Log.i(Tag, "levelImgWidth:" + levelImgWidth + ",levelImgHeight:" + levelImgHeight);
}
public Rect getTextWH(String text, int textSize) {
Paint pFont = new Paint();
Rect rect = new Rect();
pFont.setTextSize(textSize);
pFont.getTextBounds(text, 0, text.length(), rect);
return rect;
}
//图片等级与线条的间距
private int padding_img = 20;
//线条与上面文字的间距
private int padding_text = 20;
于是由于规定死了进度条的宽度为20.那么我就指定笔触的宽度为10,这个在进度条的首尾留出笔触的宽度,就可以看到弧度效果了。
private int cap = 10;//笔触宽度
private int lineWidth = 20;//进度条宽度
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = getPaddingTop() + getPaddingBottom() + lineWidth + padding_img + levelImgHeight + 20 + textHeight + padding_text;
setMeasuredDimension(getMeasuredWidth(), height);
}
先绘制没有设置进度值的时候,默认六个都是灰色的图片,当我们有等级值的时候,我们就要根据等级,计算出下面的等级图片,很简单,哪一个数组来存放这些图片,每次设置等级值的时候都重新计算,就可以达到动态显示效果了。
首先根据等级值,计算等级,并且计算它实际应该有多宽
//根据当前值,按照比例,计算它该有的长度,每个刻度的长度一样,但是每个刻度的差值不一样,
//这里就根据比例来计算
public int getCurrentDialLength() {
getDialAllLength();
if (allLength > 0 && datas.size() > 0 && currentDialvalue > 0) {
int pre = allLength / (datas.size());
for (int i = 0; i < datas.size(); i++) {
UserLevelDial dial = datas.get(i);
if (currentDialvalue <= dial.dial_e && currentDialvalue >= dial.dial_s) {
this.currentImg = i;
cDialLenth = pre * i + (int) (pre * ((currentDialvalue - dial.dial_s) / ((float) dial.dial_e - dial.dial_s)));
Log.i(Tag, "i:" + i);
break;
}
}
}
if (currentDialvalue > datas.get(datas.size() - 1).dial_e) {
this.currentImg = datas.size();
cDialLenth = allLength;
}
Log.i(Tag, "cDialLenth:" + cDialLenth);
//重新设置等级图片
setLevelImgs();
return cDialLenth;
}
private int[] levelimgs_gray = {R.drawable.grade_v1, R.drawable.grade_v2, R.drawable.grade_v3,
R.drawable.grade_v4, R.drawable.grade_v5, R.drawable.grade_v6};
private int[] levelimgs_light = {R.drawable.grade_v1_arrive, R.drawable.grade_v2_arrive, R.drawable.grade_v3_arrive,
R.drawable.grade_v4_arrive, R.drawable.grade_v5_arrive, R.drawable.grade_v6_arrive};
private ArrayList bitmap_levelimgs_gray = new ArrayList();
private ArrayList bitmap_levelimgs_light = new ArrayList();
private ArrayList bitmap_levelimgs_show = new ArrayList();
public void setLevelImgs() {
bitmap_levelimgs_show.clear();
for (int i = 0; i < bitmap_levelimgs_gray.size(); i++) {
if (i <= currentImg) {
bitmap_levelimgs_show.add(bitmap_levelimgs_light.get(i));
} else {
bitmap_levelimgs_show.add(bitmap_levelimgs_gray.get(i));
}
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);//利用父类去绘制背景
// clearScr(canvas);
if (cDialLenth > 0) {//cDialLenth当前等级的刻度的长度,大于0才绘制上门的文字x/1500
//绘制文字
Rect rect = getTextWH(currentDialvalue + "", textSize);
Rect rect2 = getTextWH("/" + maxValue, textSize);
int text_pw = cDialLenth < rect.width() ? 0 : cDialLenth - rect.width();
text_pw += getPaddingLeft();
//修正边界
int maxw = allLength - rect.width() - rect2.width() + cap * 2 + getPaddingLeft() - 5;
text_pw = text_pw > maxw ? maxw : text_pw;
Log.i(Tag, "textgetPaddingTop:" + getPaddingTop());
int text_ph = getPaddingTop() +rect.height();
String v_str = String.valueOf(currentDialvalue);
canvas.drawText(v_str, text_pw, text_ph, paint_text_value);
int text_pw2 = text_pw + rect.width() + 5;
canvas.drawText("/" + maxValue, text_pw2, text_ph, paint_text_total);
}
int bgline_ph = lineWidth / 2 + 1 + getPaddingTop() + textHeight + padding_text;
canvas.drawLine(getPaddingLeft() + cap, bgline_ph, getMeasuredWidth() - getPaddingRight() - cap, bgline_ph, paint_bg);
linearGradient = new LinearGradient(getPaddingLeft(), 0, cDialLenth, 0, new int[]{getResources().getColor(R.color.userlevels1), getResources().getColor(R.color.userlevels2)}, null, LinearGradient.TileMode.CLAMP);
paint_first.setShader(linearGradient);
canvas.drawLine(getPaddingLeft() + cap, bgline_ph, cDialLenth + getPaddingLeft() + cap, bgline_ph, paint_first);
drawLevel(canvas);
}
/**
* 设置当前刻度
*/
public void setCurrentDialvalue(int dial) {
if (null != valueAnimator && valueAnimator.isRunning()) {
valueAnimator.cancel();
}
valueAnimator = ValueAnimator.ofInt(0, dial);
valueAnimator.setDuration(dial > 500 ? 2000 : 1000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
currentDialvalue = (int) valueAnimator.getAnimatedValue();
getCurrentDialLength();
invalidate();
}
});
valueAnimator.start();
}
源码下载