这是一个自定义ProgressBar的案例,自定义水平进度条,运行效果如图:
要定义这个水平进度条需要有如下的属性:即attrs.xml代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="progress_unreach_color" format="color"></attr>
<attr name="progress_unreach_height" format="dimension"></attr>
<attr name="progress_reach_color" format="color"></attr>
<attr name="progress_reach_height" format="dimension"></attr>
<attr name="progress_text_color" format="color"></attr>
<attr name="progress_text_size" format="dimension"></attr>
<attr name="progress_text_offset" format="dimension"></attr>
<declare-styleable name="HorizontalProgressBarWithProgress">
<attr name="progress_unreach_color" ></attr>
<attr name="progress_unreach_height" ></attr>
<attr name="progress_reach_color" ></attr>
<attr name="progress_reach_height" ></attr>
<attr name="progress_text_color" ></attr>
<attr name="progress_text_size" ></attr>
<attr name="progress_text_offset" ></attr>
</declare-styleable>
</resources>
HorizontalProgressBarWithProgress.java的代码如下:
</pre><pre name="code" class="java">package com.tommy.view;
import com.tommy.progressbardemo.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.BaseAdapter;
import android.widget.ProgressBar;
/**
* 自定义一个水平的附带进度的ProgressBar
* @author Tommy
*
*/
public class HorizontalProgressBarWithProgress extends ProgressBar{
private static final int DEFAULT_TEXT_SIZE = 10;//sp
private static final int DEFAULT_TEXT_COLOR = 0xFFFC00D1;
private static final int DEFAULT_UNREACH_COLOR = 0xFFD3D6DA;
private static final int DEFAULT_REACH_COLOR = 0xFFFC00D1;
private static final int DEFAULT_UNREACH_HEIGHT = 2;//dp
private static final int DEFAULT_REACH_HEIGHT = 2;//dp
private static final int DEFAULT_TEXT_OFFSET = 10;//dp
private int mTextSize = sp2px(DEFAULT_TEXT_SIZE);
private int mTextColor = DEFAULT_TEXT_COLOR;
private int mUnReachColor = DEFAULT_UNREACH_COLOR;
private int mUnReachHeight = dp2px(DEFAULT_UNREACH_HEIGHT);
private int mReachColor = DEFAULT_REACH_COLOR;
private int mReachHeight = dp2px(DEFAULT_REACH_HEIGHT);
private int mTextOffset = dp2px(DEFAULT_TEXT_OFFSET);
private Paint mPaint = new Paint();
/**
* 该值是ProgressBar的真正的值,是getWidth - padding的值,可能在onMeasure中初始化,
* 在onDraw中使用。
*/
private int mRealWidth = 0;
public HorizontalProgressBarWithProgress(Context context,
AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
obtainStyledAttrs(attrs);
}
public HorizontalProgressBarWithProgress(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public HorizontalProgressBarWithProgress(Context context) {
this(context,null);
}
/**
* 获取自定义属性的值
* @param attrs
*/
private void obtainStyledAttrs(AttributeSet attrs) {
TypedArray ta = getContext().obtainStyledAttributes
(attrs, R.styleable.HorizontalProgressBarWithProgress);
mTextSize = (int) ta.getDimension
(R.styleable.HorizontalProgressBarWithProgress_progress_text_size, mTextSize);
mTextColor = ta.getColor
(R.styleable.HorizontalProgressBarWithProgress_progress_text_color, mTextColor);
mUnReachColor = ta.getColor
(R.styleable.HorizontalProgressBarWithProgress_progress_unreach_color, mUnReachColor);
mUnReachHeight = (int) ta.getDimension
(R.styleable.HorizontalProgressBarWithProgress_progress_unreach_height, mUnReachHeight);
mReachColor = ta.getColor
(R.styleable.HorizontalProgressBarWithProgress_progress_reach_color, mReachColor);
mReachHeight = (int) ta.getDimension
(R.styleable.HorizontalProgressBarWithProgress_progress_reach_height, mReachHeight);
mTextOffset = (int) ta.getDimension
(R.styleable.HorizontalProgressBarWithProgress_progress_text_offset, mTextOffset);
ta.recycle();
mPaint.setTextSize(mTextSize);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec,
int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthVal = MeasureSpec.getSize(widthMeasureSpec);
int heigthVal = measureHeight(heightMeasureSpec);
setMeasuredDimension(widthVal, heigthVal);
mRealWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
}
/**
* 测量高度
* @param heightMeasureSpec
* @return
*/
private int measureHeight(int heightMeasureSpec) {
int result = 0;
int mode = MeasureSpec.getMode(heightMeasureSpec);
int size = MeasureSpec.getSize(heightMeasureSpec);
//MeasureSpec.EXACTLY这个值意思是说,在布局中我们用到了一个精确的值,比如wrap_content,200dp这一类值。
if(mode == MeasureSpec.EXACTLY){
result = size;
}else {
int textHeight = (int) (mPaint.descent() - mPaint.ascent());
result = getPaddingBottom() + getPaddingTop() +
Math.max(Math.max(mReachHeight, mUnReachHeight), Math.abs(textHeight));
if(mode == MeasureSpec.AT_MOST){
result = Math.min(result, size);
}
}
return result;
}
@Override
protected synchronized void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.translate(getPaddingLeft(), getHeight()/2);
boolean noNeedUnReach = false;
//draw reachBar
String text = getProgress() + "%";
int textWidth = (int) mPaint.measureText(text);
float radio = getProgress() * 1.0F/getMax();
float progressX = radio * mRealWidth;
if(progressX > (mRealWidth - textWidth)){
progressX = mRealWidth - textWidth;
noNeedUnReach = true;
}
float endX = progressX - mTextOffset / 2;
if(endX > 0){
mPaint.setColor(mReachColor);
mPaint.setStrokeWidth(mReachHeight);
// if(noNeedUnReach){
// canvas.drawLine(0, 0, endX - textWidth, 0, mPaint);
// }
canvas.drawLine(0, 0, endX , 0, mPaint);
}
//draw text
mPaint.setColor(mTextColor);
int y = (int) (-( mPaint.descent() + mPaint.ascent() ) / 2);
canvas.drawText(text, progressX, y, mPaint);
//draw unReachBar
if(!noNeedUnReach){
float start = progressX + textWidth + mTextOffset/2;
mPaint.setColor(mUnReachColor);
mPaint.setStrokeWidth(mUnReachHeight);
canvas.drawLine(start, 0, mRealWidth, 0, mPaint);
}
canvas.restore();
}
/**
* 用于将dp转化为px的工具方法。
* @param dpVal
* @return
*/
private int dp2px(int dpVal){
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal,
getResources().getDisplayMetrics());
}
/**
* 用于将dp转化为px的工具方法。
* @param spVal
* @return
*/
private int sp2px(int spVal){
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal,
getResources().getDisplayMetrics());
}
}
软后在activity_main.xml中去引用这个自定义控件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:tommy="http://schemas.android.com/apk/res/com.tommy.progressbardemo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<com.tommy.view.HorizontalProgressBarWithProgress
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#44ff0000"
android:progress="50"
android:padding="15dp"
android:layout_marginTop="30dp"
/>
<com.tommy.view.HorizontalProgressBarWithProgress
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#44ff0000"
android:layout_marginTop="30dp"
android:progress="100"
android:padding="15dp"
tommy:progress_text_color="#ff000000"
tommy:progress_unreach_color="#ff000000"
/>
<com.tommy.view.HorizontalProgressBarWithProgress
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#44ff0000"
android:layout_marginTop="30dp"
android:progress="30"
android:padding="15dp"
tommy:progress_text_color="#ff000000"
tommy:progress_unreach_color="#ff000000"
/>
</LinearLayout>
</ScrollView>
</LinearLayout>
MainActivity代码在这里就省略了。
这是自定义圆形进度条的一个案例:http://sumile.cn/archives/1523.html