不多说,我们先上图
先放项目地址:github
说明:
这是一个基于ProgressBar的进度条。
颜色、大小、背景都通过属性直接设置。
本项目没有做代码设置的属性的实现,可以自行加入。
使用方法:
<com.iehshx.rodhoriztalprogressbar.RodHoriztalProgressBar
android:id="@+id/mine_credit_pb_credit"
app:layout_constraintTop_toTopOf="parent"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:layout_marginTop="40dp"
app:progressbar_reach_color="@color/bule_0aaccc"
app:progressbar_reach_height="3dp"
app:progressbar_rod_bg="@mipmap/bg_rod"
app:progressbar_text_bg="@mipmap/bg_zs"
app:progressbar_text_color="#fff"
app:progressbar_text_offset_line="5dp"
app:progressbar_text_size="@dimen/fontSize_16"
app:progressbar_unreach_color="@color/bg_gray_empty"
app:progressbar_unreach_height="3dp"
tools:layout_editor_absoluteX="8dp" />
代码介绍:
RodHoriztalProgressBar
这个类只有170行,很简单。
public class RodHoriztalProgressBar extends ProgressBar {
……
}
以上就是RodHoriztalProgressBar的开始,继承ProgressBar。
private static final int DEFAULT_REACH_COLOR = 0xff24F569;
private static final int DEFAULT_UNREACH_COLOR = 0xffC0C0C0;
private static final int DEFAULT_REACH_HEIGHT = 2;
private static final int DEFAULT_UNREACH_HEIGHT = 2;
private static final int DEFAULT_TEXT_COLOR = DEFAULT_REACH_COLOR;
private static final int DEFAULT_TEXT_SIZE = 12;
private static final int DEFAULT_TEXT_OFFSET = 5;
private final Drawable mProgress;//当前进度提示文本框
private final Drawable mKedu;//背景刻度
private final int mkeduWidget;
private int mkeduHeight;
private final int mTextOffsetLine;
private int mProgressWidght;
private int mProgressHeight;
protected int mReachColor = DEFAULT_REACH_COLOR;
protected int mUnReachColor = DEFAULT_UNREACH_COLOR;
protected int mReachHeight = dp2px(DEFAULT_REACH_HEIGHT);
protected int mUnReachHeight = dp2px(DEFAULT_UNREACH_HEIGHT);
protected int mTextColor = DEFAULT_TEXT_COLOR;
protected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
protected int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);
定义了一些默认的属性值,比如背景色,文本框,刻度等等。
接下来就是初始化这些属性的值,在构造函数中初始化:
public RodHoriztalProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.RodHoriztalProgressBar);
mReachColor = ta.getColor(R.styleable.RodHoriztalProgressBar_progressbar_reach_color, mReachColor);
mUnReachColor = ta.getColor(R.styleable.RodHoriztalProgressBar_progressbar_unreach_color, mUnReachColor);
mReachHeight = (int) ta.getDimension(R.styleable.RodHoriztalProgressBar_progressbar_reach_height, mReachHeight);
mUnReachHeight = (int) ta.getDimension(R.styleable.RodHoriztalProgressBar_progressbar_unreach_height, mUnReachHeight);
mTextColor = ta.getColor(R.styleable.RodHoriztalProgressBar_progressbar_text_color, mTextColor);
mTextSize = (int) ta.getDimension(R.styleable.RodHoriztalProgressBar_progressbar_text_size, mTextSize);
mTextOffset = (int) ta.getDimension(R.styleable.RodHoriztalProgressBar_progressbar_text_offset, mTextOffset);
mTextOffsetLine = (int) ta.getDimension(R.styleable.RodHoriztalProgressBar_progressbar_text_offset, mTextOffset);
mKedu = ta.getDrawable(R.styleable.RodHoriztalProgressBar_progressbar_rod_bg);
mProgress = ta.getDrawable(R.styleable.RodHoriztalProgressBar_progressbar_text_bg);
ta.recycle();
if (mProgress != null) {
mProgressWidght = mProgress.getIntrinsicWidth();
mProgressHeight = mProgress.getIntrinsicHeight();
}
if (mKedu != null)
mkeduHeight = mKedu.getIntrinsicHeight();
mkeduWidget = mKedu.getIntrinsicWidth();
mPaint.setTextSize(mTextSize);
}
好了,以上把属性都初始化完成了。也不多,都很简单。
下面就是控件的绘制了:
首先onMeasure,这个是测量控件的大小
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int heightVal = mProgressHeight + mTextOffsetLine + mReachHeight + mkeduHeight;
setMeasuredDimension(mkeduWidget, heightVal);
}
我们根据进度条、刻度尺的款来计算控件需要绘制的宽和高。
然后onDraw。就是用来绘制控件的:
@Override
protected synchronized void onDraw(Canvas canvas) {
String text = getProgress() + "%";
boolean noNeedUnrechBar = false;
float radio = getProgress() * 1.0f / getMax();
float progressX = mkeduWidget * radio;
if (progressX > mkeduWidget) {
progressX = mkeduWidget;
noNeedUnrechBar = true;
}
//画文本框
if (mProgress != null) {
//计算文本框应该在的X坐标
float bgStartX = (int) progressX - (mProgressWidght / 2);
float bgEndX = progressX + (mProgressWidght / 2);
if (bgStartX>=mkeduWidget-mProgressWidght){
bgStartX = mkeduWidget - mProgressWidght;
}
//文本框的坐标校验
if (bgEndX>=mkeduWidget){
bgEndX = mkeduWidget;
}
if (bgEndX<mProgressWidght){
bgEndX = mProgressWidght;
}
if (bgStartX<=0){
bgStartX = 0;
}
mProgress.setBounds((int) bgStartX, 0, (int) bgEndX, mProgressHeight);
mProgress.draw(canvas);
//计算文本的X坐标和Y坐标
int textWH = getTextWidth(text)/2;//文本的一半长度
int progressBgWH = mProgressWidght /2; //进度文本框的一半
float progressTxtStartX = bgStartX + ( progressBgWH - textWH);
float progressTxtStartY = mProgressHeight / 2 + 5;
if (progressTxtStartX >= mkeduWidget - progressBgWH){
progressTxtStartX = mkeduWidget - progressBgWH- textWH;
}
if (progressTxtStartX <= (progressBgWH - textWH)){
progressTxtStartX = progressBgWH - textWH;
}
mPaint.setColor(mTextColor);
canvas.drawText(text, progressTxtStartX, progressTxtStartY, mPaint);
}
//画布移动到进度条
canvas.save();
canvas.translate(getPaddingLeft(), mProgressHeight + mTextOffsetLine);
//draw 进度条
mPaint.setColor(mReachColor);
mPaint.setStrokeWidth(mReachHeight);
canvas.drawLine(0, 0 + mReachHeight, progressX, 0 + mReachHeight, mPaint);
//draw text
//画刻度
if (mKedu != null) {
mKedu.setBounds(0, 0, mkeduWidget, mkeduHeight);
mKedu.draw(canvas);
}
if (!noNeedUnrechBar) {
mPaint.setColor(mUnReachColor);
mPaint.setStrokeWidth(mUnReachHeight);
float startX = progressX;
canvas.drawLine(startX, mProgressHeight, mkeduWidget, mProgressHeight, mPaint);
}
canvas.restore();
}
都是很简单的代码,都有备注。 主要就是绘制文本框,计算文本框的坐标,计算文本的坐标,画进度条,画刻度等等的一些逻辑。
注:getTextWidth(); 是用来计算当前文本的长度的,将文本放在文本框的中间。代码如下:
public int getTextWidth(String content) {
int width = 0;
if (content != null && content.length() > 0) {
int length = content.length();
float[] widths = new float[length];
mPaint.getTextWidths(content, widths);
for (int i = 0; i < length; i++) {
width += (int) Math.ceil(widths[i]);
}
}
return width;
}
以上就是RodHoriztalProgressBar的全部内容。东西真的很少,但是用起来还是挺方便的。
好了,谢谢你来看我的简书,在此表示感谢。
如果你有好的建议 或者 比较好玩的控件,可以和我说,我们一起学习。