自定义属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="HorizentailProgressBar">
<attr name="progress_text_color" format="color" />
<attr name="progress_text_size" format="dimension" />
<attr name="progress_text_offset" format="dimension" />
<attr name="progress_unreach_color" format="color" />
<attr name="progress_unreach_height" format="dimension" />
<attr name="progress_reach_color" format="color" />
<attr name="progress_reach_height" format="dimension" />
</declare-styleable>
</resources>
创建横向进度条类
public class HorizentailProgressBar extends ProgressBar {
// 字体颜色
private int textColor = 0x66FF0000;
// 字体大小
private int textSize = sp2px(16);
// 字体两旁的间隔
private int textOffset = dp2px(10);
// 完成路径的颜色
private int reachColor = 0x66FF0000;
// 完成路径的高度
private int reachHeight = dp2px(2);
// 未完成路径的颜色
private int unreachColor = 0x22FF0000;
// 未完成路径的颜色
private int unreachHeight = dp2px(2);
// 控件的真实宽度
private int realWidth = 0;
// 是否需要绘制未完成路径
private boolean unreachFlag = true;
private Paint paint = new Paint();
public HorizentailProgressBar(Context context) {
this(context, null);
}
public HorizentailProgressBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizentailProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
obtainStyleAttrs(context, attrs);
}
private void obtainStyleAttrs(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.HorizentailProgressBar);
textSize = ta.getDimensionPixelSize(R.styleable.HorizentailProgressBar_progress_text_size, textSize);
textColor = ta.getColor(R.styleable.HorizentailProgressBar_progress_text_color, textColor);
textOffset = (int) ta.getDimension(R.styleable.HorizentailProgressBar_progress_text_offset, textOffset);
reachColor = ta.getColor(R.styleable.HorizentailProgressBar_progress_reach_color, reachColor);
reachHeight = (int) ta.getDimension(R.styleable.HorizentailProgressBar_progress_reach_height, reachHeight);
unreachColor = ta.getColor(R.styleable.HorizentailProgressBar_progress_unreach_color, unreachColor);
unreachHeight = (int) ta.getDimension(R.styleable.HorizentailProgressBar_progress_unreach_height, unreachHeight);
ta.recycle();
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = measureHeight(heightMeasureSpec);
setMeasuredDimension(width, height);
// 获取控件真实的宽度
realWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
}
// 获取控件的高度
private int measureHeight(int heightMeasureSpec) {
int result = 0;
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.EXACTLY) { // 具体高度,如30dp...
result = heightSize;
} else { // 看是字体高,还是ProgressBar的线高
int lineHeight = dp2px(Math.max(unreachHeight, reachHeight));
int textHeight = sp2px((int) Math.abs((paint.descent() - paint.ascent())));
if (lineHeight > textHeight) {
result = getPaddingTop() + getPaddingBottom() + lineHeight;
} else {
result = getPaddingTop() + getPaddingBottom() + textHeight;
}
}
return result;
}
@Override
protected synchronized void onDraw(Canvas canvas) {
canvas.save();
// 开始绘制的偏移
canvas.translate(getPaddingLeft(), getHeight() / 2);
// 进度值
String text = getProgress() + "%";
int textWidth = (int) paint.measureText(text);
// 绘制完成路径
float end = (getProgress() * 1.0f / getMax()) * realWidth;
if (end + textOffset + textWidth >= realWidth) {
end = realWidth - textOffset - textWidth;
unreachFlag = false;
}
paint.setColor(reachColor);
paint.setStrokeWidth(reachHeight);
canvas.drawLine(0, 0, end, 0, paint);
// 绘制进度值
float x = end + textOffset / 2;
paint.setColor(textColor);
paint.setTextSize(textSize);
int y = (int) (-(paint.descent() + paint.ascent()) / 2);
canvas.drawText(text, x, y, paint);
// 绘制未完成的路径
if (unreachFlag) {
float start = end + textWidth + textOffset;
paint.setColor(unreachColor);
paint.setStrokeWidth(unreachHeight);
canvas.drawLine(start, 0, realWidth, 0, paint);
}
canvas.restore();
}
private int dp2px(int value) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value,
getResources().getDisplayMetrics());
}
private int sp2px(int value) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value,
getResources().getDisplayMetrics());
}
}
在布局文件中引用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.zc.myapp.views.demo.HorizentailProgressBar
android:id="@+id/progress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
app:progress_reach_color="#77FF0000"
app:progress_reach_height="2dp"
app:progress_text_color="#77FF0000"
app:progress_text_size="16sp"
app:progress_text_offset="10dp"
app:progress_unreach_color="#33FF0000"
app:progress_unreach_height="2dp"
android:progress="0" />
</LinearLayout>
在Activity中使用
public class MainActivity extends AppCompatActivity {
private HorizentailProgressBar progressBar;
private Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
int progress = progressBar.getProgress();
progressBar.setProgress(++progress);
if (progress >= 100) {
handler.removeMessages(111);
}
handler.sendEmptyMessageDelayed(111, 100);
}
};
@SuppressLint("WrongViewCast")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
progressBar = findViewById(R.id.progress);
handler.sendEmptyMessage(111);
}
}