概览:
Android应用经常大家会遇到进度条上方活着下方显示进度标记样式进度框,大家遇到这个现在github上有了很多实现,大家会发现别人的东西都会有各种不满足自己样式的样式, 大家马上想到的就是去重写第三方的控件,既然要重写,那为啥不重写系统自带的ProgressBar和SeekBar呢?我这里就是重写的系统SeekBar实现进度条下方显示进度标记,先来效果图:
SeekBar属性:
大家都知道ProgressBar是不支持手动拖动进度的,然而SeekBar是支持拖动的,我这里为了通用使用的SeekBar作为重写对象。SeekBar常用属性:
1. android:progressDrawable 进度背景包含了背景(background),进度颜色(progress) 进度默认颜色(secondProgress);
2. android:thumb 可以手动拖动的按钮。
代码实现:
1.实现方法
通过drawPath和drawCircle方法画出水滴标记,计算进度比例和控件宽度确定标记的位置。
2. 代码实现
计算水滴大小及文本大小:
//文本背景
mTabPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTabPaint.setColor(mColor > 0 ? getResources().getColor(mColor) : Color.BLUE);
//画进度百分比文本
mPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(mTextColor > 0 ? getResources().getColor(mTextColor) : Color.WHITE);
mPaint.setTextSize(getContext().getResources().getDisplayMetrics().density * 10);
Paint.FontMetrics metrics = mPaint.getFontMetrics();
mFontBottom = metrics.bottom;
mFontTop = metrics.top;
mTextHeight = metrics.bottom - metrics.top;
mTextWidth = mPaint.measureText("88%");
setPadding((int) (mTextWidth / 2 + mPadding), 0, (int) (mTextWidth / 2 + mPadding), 0);
重写onMeasure方法,调整高度显示标记:
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int resetHeight = MeasureSpec.makeMeasureSpec((int) (5 * mTextHeight), MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, resetHeight);
setTranslationY(-mTextHeight * 1);
}
重写onDraw方法,画圆,画圆切边路径,画文本:
if (100 == getProgress()) {
mPaint.setTextSize(getContext().getResources().getDisplayMetrics().density * (mTextSize - 2));
} else {
mPaint.setTextSize(getContext().getResources().getDisplayMetrics().density * mTextSize);
}
float radius = mTextWidth / 2 + mPadding; //水滴圆半径
float progressX = (getMeasuredWidth() - 2 * radius) * getProgress() / getMax(); //进度条X
float textCenterX = progressX + getPaddingLeft(); //文本中心X
float textLeft = progressX - mTextWidth / 2 + getPaddingLeft(); //文本开始X
float baselineY = getMeasuredHeight() / 2 + 2 * mTextHeight + mFontTop; //文本基线Y
float circleY = baselineY + (mFontBottom + mFontTop) / 2; //圆心Y
//画水滴文本圆
canvas.drawCircle(textCenterX, circleY + mTextWidth / 2, radius, mTabPaint);
//画水滴圆切边三角形
Path path = new Path();
double tangle = Math.acos(radius / mTextWidth);
float rightX = (float) (textCenterX + Math.sin(tangle) * radius);
float rightY = (float) (circleY + mTextWidth / 2 - Math.cos(tangle) * radius);
float leftX = (float) (textCenterX - Math.sin(tangle) * radius);
float leftY = (float) (circleY + mTextWidth / 2 - Math.cos(tangle) * radius);
path.moveTo(textCenterX, circleY - mTextWidth / 2);
path.lineTo(rightX, rightY);
path.lineTo(leftX, leftY);
path.close();
canvas.drawPath(path, mTabPaint);
//画文本
String text = String.format("%02d%%", getProgress());
canvas.drawText(text, textLeft, baselineY + mTextWidth / 2, mPaint);
3. 大功告成
是不是很简单,不用使用第三方组件,而且SeekBar的原来属性依然可以用。
实例代码
github地址:https://github.com/the-liuchao/TagSeekBar.git