Android自定义View实现带数字的进度条实例代码

第一步、效果展示

图1、蓝色的进度条

图2、红色的进度条

图3、多条颜色不同的进度条

图4、多条颜色不同的进度条

第二步、自定义ProgressBar实现带数字的进度条

0、项目结构

如上图所示:library项目为自定义的带数字的进度条NumberProgressBar的具体实现,demo项目为示例项目以工程依赖的方式引用library项目,然后使用自定义的带数字的进度条NumberProgressBar来做展示

如上图所示:自定义的带数字的进度条的library项目的结构图

如上图所示:demo项目的结构图

1、绘制步骤分析

如上面几幅图形所示。这个进度条的可以分为以下三部分:

reacherd area :表示当前进度值之前文本的进度条(长方形)

text area :表示当前进度值文本

unreacherd area :当前进度值文本之后的进度条(长方形)

按照上面的分析,我们要实现带数字的进度条,只需要按照以下三个步骤绘制即可实现:

1、绘制reacherd area(当前进度值之前文本的进度条)

2、绘制text area(当前进度值文本)

3、绘制unreacherd area(当前进度值文本之后的进度条) 即可。

2、自定义属性

由于我们发现以上三个部分的颜色、字体大小、进度条的最大值、表示进度条的长方形的高度等属性都可以改变,从而展现出不同的界面效果。

因此我们将这些属性都做自定义属性。这样我们就能够做到像android官方提供的那些组件一样用xml来定义它的属性了。

1、定义自己的属性配置文件:attr.xml

在res/values文件下定义一个attrs.xml文件,res/values/attrs.xml定义代码如下所示:

<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="NumberProgressBar"> <!--进度条的当前进度值--> <attr name="progress_current" format="integer"/> <!--进度条的最大进度值--> <attr name="progress_max" format="integer"/> <!--当前进度值文本之后的进度条颜色--> <attr name="progress_unreached_color" format="color"/> <!--当前进度值文本之前的进度条颜色--> <attr name="progress_reached_color" format="color"/> <!-- 当前进度值文本之前的进度条的高度--> <attr name="progress_reached_bar_height" format="dimension"/> <!--当前进度值文本之后的进度条的高度--> <attr name="progress_unreached_bar_height" format="dimension"/> <!--当前进度值文本的字体大小--> <attr name="progress_text_size" format="dimension"/> <!--当前进度值文本的颜色--> <attr name="progress_text_color" format="color"/> <!--当前进度值之前文本的间距--> <attr name="progress_text_offset" format="dimension"/> <!--当前进度值文本是否可见--> <attr name="progress_text_visibility" format="enum"> <enum name="visible" value="0"/> <enum name="invisible" value="1"/> </attr> </declare-styleable> <declare-styleable name="Themes"> <attr name="numberProgressBarStyle" format="reference"/> </declare-styleable> </resources>

2、定义主题配置文件:styles.xml

在res/values文件下定义一个styles.xml文件,里面定义一些基本的主题选项,以备用户可以选择使用。res/values/styles.xml定义代码如下所示:

<?xml version="1.0" encoding="utf-8"?> <resources> <style name="NumberProgressBar_Default"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">match_parent</item> <item name="progress_max">100</item> <item name="progress_current">0</item> <item name="progress_unreached_color">#CCCCCC</item> <item name="progress_reached_color">#3498DB</item> <item name="progress_text_size">10sp</item> <item name="progress_text_color">#3498DB</item> <item name="progress_reached_bar_height">1.5dp</item> <item name="progress_unreached_bar_height">0.75dp</item> </style> <style name="NumberProgressBar_Passing_Green"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">match_parent</item> <item name="progress_max">100</item> <item name="progress_current">0</item> <item name="progress_unreached_color">#CCCCCC</item> <item name="progress_reached_color">#70A800</item> <item name="progress_text_size">10sp</item> <item name="progress_text_color">#70A800</item> <item name="progress_reached_bar_height">1.5dp</item> <item name="progress_unreached_bar_height">0.75dp</item> </style> <style name="NumberProgressBar_Beauty_Red"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">match_parent</item> <item name="progress_max">100</item> <item name="progress_current">0</item> <item name="progress_unreached_color">#CCCCCC</item> <item name="progress_reached_color">#FF3D7F</item> <item name="progress_text_size">10sp</item> <item name="progress_text_color">#FF3D7F</item> <item name="progress_reached_bar_height">1.5dp</item> <item name="progress_unreached_bar_height">0.75dp</item> </style> <style name="NumberProgressBar_Warning_Red"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">match_parent</item> <item name="progress_max">100</item> <item name="progress_current">0</item> <item name="progress_unreached_color">#CCCCCC</item> <item name="progress_reached_color">#E74C3C</item> <item name="progress_text_size">10sp</item> <item name="progress_text_color">#E74C3C</item> <item name="progress_reached_bar_height">1.5dp</item> <item name="progress_unreached_bar_height">0.75dp</item> </style> <style name="NumberProgressBar_Relax_Blue"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">match_parent</item> <item name="progress_max">100</item> <item name="progress_current">0</item> <item name="progress_unreached_color">#CCCCCC</item> <item name="progress_reached_color">#6DBCDB</item> <item name="progress_text_size">10sp</item> <item name="progress_text_color">#6DBCDB</item> <item name="progress_reached_bar_height">1.5dp</item> <item name="progress_unreached_bar_height">0.75dp</item> </style> <style name="NumberProgressBar_Grace_Yellow"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">match_parent</item> <item name="progress_max">100</item> <item name="progress_current">0</item> <item name="progress_unreached_color">#CCCCCC</item> <item name="progress_reached_color">#FFC73B</item> <item name="progress_text_size">10sp</item> <item name="progress_text_color">#FFC73B</item> <item name="progress_reached_bar_height">1.5dp</item> <item name="progress_unreached_bar_height">0.75dp</item> </style> <style name="NumberProgressBar_Funny_Orange"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">match_parent</item> <item name="progress_max">100</item> <item name="progress_current">0</item> <item name="progress_unreached_color">#CCCCCC</item> <item name="progress_reached_color">#FF530D</item> <item name="progress_text_size">10sp</item> <item name="progress_text_color">#FF530D</item> <item name="progress_reached_bar_height">1.5dp</item> <item name="progress_unreached_bar_height">0.75dp</item> </style> <style name="NumberProgressBar_Twinkle_Night"> <item name="android:layout_height">wrap_content</item> <item name="android:layout_width">match_parent</item> <item name="progress_max">100</item> <item name="progress_current">0</item> <item name="progress_unreached_color">#CCCCCC</item> <item name="progress_reached_color">#ECF0F1</item> <item name="progress_text_size">10sp</item> <item name="progress_text_color">#ECF0F1</item> <item name="progress_reached_bar_height">1.5dp</item> <item name="progress_unreached_bar_height">0.75dp</item> </style> </resources>

3、自定义View实现带数字的进度条

package com.daimajia.numberprogressbar; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.os.Bundle; import android.os.Parcelable; import android.util.AttributeSet; import android.view.View; import static com.daimajia.numberprogressbar.NumberProgressBar.ProgressTextVisibility.Invisible; import static com.daimajia.numberprogressbar.NumberProgressBar.ProgressTextVisibility.Visible; /** * Created by daimajia on 14-4-30. */ public class NumberProgressBar extends View { /** * 进度值最大值 */ private int mMaxProgress = 100; /** * Current progress, can not exceed the max progress. * 当前进度值,不能超过进度值最大值 */ private int mCurrentProgress = 0; /** * The progress area bar color. * 当前进度值文本之前的进度条颜色 */ private int mReachedBarColor; /** * The bar unreached area color. * 当前进度值文本之后的进度条颜色 */ private int mUnreachedBarColor; /** * The progress text color. * 当前进度值文本的颜色 */ private int mTextColor; /** * The progress text size. * 当前进度值文本的字体大小 */ private float mTextSize; /** * The height of the reached area. * 当前进度值文本之前的进度条的高度 */ private float mReachedBarHeight; /** * The height of the unreached area. * 当前进度值文本之后的进度条的高度 */ private float mUnreachedBarHeight; /** * The suffix of the number. * 当前进度值的百分比后缀 */ private String mSuffix = "%"; /** * The prefix. * 当前进度值的百分比前缀 */ private String mPrefix = ""; //当前进度值文本的默认颜色 private final int default_text_color = Color.rgb(66, 145, 241); //当前进度值文本的字体大小 private final float default_text_size; //当前进度值之前的默认进度条颜色 private final int default_reached_color = Color.rgb(66, 145, 241); //当前进度值之后的默认进度条颜色 private final int default_unreached_color = Color.rgb(204, 204, 204); //当前进度值之前文本的默认间距 private final float default_progress_text_offset; //当前进度值文本之前的进度条的默认高度 private final float default_reached_bar_height; //当前进度值文本之后的进度条的默认高度 private final float default_unreached_bar_height; /** * For save and restore instance of progressbar. */ private static final String INSTANCE_STATE = "saved_instance"; private static final String INSTANCE_TEXT_COLOR = "text_color"; private static final String INSTANCE_TEXT_SIZE = "text_size"; private static final String INSTANCE_REACHED_BAR_HEIGHT = "reached_bar_height"; private static final String INSTANCE_REACHED_BAR_COLOR = "reached_bar_color"; private static final String INSTANCE_UNREACHED_BAR_HEIGHT = "unreached_bar_height"; private static final String INSTANCE_UNREACHED_BAR_COLOR = "unreached_bar_color"; private static final String INSTANCE_MAX = "max"; private static final String INSTANCE_PROGRESS = "progress"; private static final String INSTANCE_SUFFIX = "suffix"; private static final String INSTANCE_PREFIX = "prefix"; private static final String INSTANCE_TEXT_VISIBILITY = "text_visibility"; //默认显示当前进度值文本 0为显示,1为不显示 private static final int PROGRESS_TEXT_VISIBLE = 0; /** * The width of the text that to be drawn. * 要绘制的当前进度值的文本的宽度 */ private float mDrawTextWidth; /** * The drawn text start. * 要绘制的当前进度值的文本的起始位置 */ private float mDrawTextStart; /** * The drawn text end. * 要绘制的当前进度值的文本的结束位置 */ private float mDrawTextEnd; /** * The text that to be drawn in onDraw(). * 要绘制的当前进度值的文本 */ private String mCurrentDrawText; /** * The Paint of the reached area. * 绘制当前进度值文本之前的进度条的画笔 */ private Paint mReachedBarPaint; /** * The Paint of the unreached area. * 绘制当前进度值文本之后的进度条的画笔 */ private Paint mUnreachedBarPaint; /** * The Paint of the progress text. * 绘制当前进度值文本的的画笔 */ private Paint mTextPaint; /** * Unreached bar area to draw rect. * 当前进度值文本之后的进度条(长方形) */ private RectF mUnreachedRectF = new RectF(0, 0, 0, 0); /** * Reached bar area rect. * 当前进度值之前文本的进度条(长方形) */ private RectF mReachedRectF = new RectF(0, 0, 0, 0); /** * The progress text offset. * 当前进度值之前文本的间距 */ private float mOffset; /** * Determine if need to draw unreached area. * 是否绘制当前进度值之后的进度条 */ private boolean mDrawUnreachedBar = true; /** * 是否绘制当前进度值之前的进度条 */ private boolean mDrawReachedBar = true; /** * 是否绘制当前进度值文本 */ private boolean mIfDrawText = true; /** * Listener */ private OnProgressBarListener mListener; public enum ProgressTextVisibility { Visible, Invisible } public NumberProgressBar(Context context) { this(context, null); } public NumberProgressBar(Context context, AttributeSet attrs) { this(context, attrs, R.attr.numberProgressBarStyle); } public NumberProgressBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); default_reached_bar_height = dp2px(1.5f); default_unreached_bar_height = dp2px(1.0f); default_text_size = sp2px(10); default_progress_text_offset = dp2px(3.0f); //获取自定义属性 final TypedArray attributes = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NumberProgressBar, defStyleAttr, 0); mReachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_reached_color, default_reached_color); mUnreachedBarColor = attributes.getColor(R.styleable.NumberProgressBar_progress_unreached_color, default_unreached_color); mTextColor = attributes.getColor(R.styleable.NumberProgressBar_progress_text_color, default_text_color); mTextSize = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_size, default_text_size); mReachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_reached_bar_height, default_reached_bar_height); mUnreachedBarHeight = attributes.getDimension(R.styleable.NumberProgressBar_progress_unreached_bar_height, default_unreached_bar_height); mOffset = attributes.getDimension(R.styleable.NumberProgressBar_progress_text_offset, default_progress_text_offset); int textVisible = attributes.getInt(R.styleable.NumberProgressBar_progress_text_visibility, PROGRESS_TEXT_VISIBLE); if (textVisible != PROGRESS_TEXT_VISIBLE) { mIfDrawText = false; } setProgress(attributes.getInt(R.styleable.NumberProgressBar_progress_current, 0)); setMax(attributes.getInt(R.styleable.NumberProgressBar_progress_max, 100)); //回收 TypedArray,用于后续调用时可复用之。回收到TypedArrayPool池中,以备后用 attributes.recycle(); initializePainters(); } @Override protected int getSuggestedMinimumWidth() { return (int) mTextSize; } @Override protected int getSuggestedMinimumHeight() { return Math.max((int) mTextSize, Math.max((int) mReachedBarHeight, (int) mUnreachedBarHeight)); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * MeasureSpec参数的值为int型,分为高32位和低16为, * 高32位保存的是specMode,低16位表示specSize, * * specMode分三种: 1、MeasureSpec.UNSPECIFIED,父视图不对子视图施加任何限制,子视图可以得到任意想要的大小; 2、MeasureSpec.EXACTLY,父视图希望子视图的大小是specSize中指定的大小; 3、MeasureSpec.AT_MOST,子视图的大小最多是specSize中的大小。 */ setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false)); } private int measure(int measureSpec, boolean isWidth) { int result; int mode = MeasureSpec.getMode(measureSpec); int size = MeasureSpec.getSize(measureSpec); int padding = isWidth ? getPaddingLeft() + getPaddingRight() : getPaddingTop() + getPaddingBottom(); /** 父决定子的确切大小,子被限定在给定的边界里,忽略本身想要的大小。 (当设置width或height为match_parent时,模式为EXACTLY,因为子view会占据剩余容器的空间,所以它大小是确定的) */ if (mode == MeasureSpec.EXACTLY) { result = size; } else { result = isWidth ? getSuggestedMinimumWidth() : getSuggestedMinimumHeight(); result += padding; /** *子最大可以达到的指定大小 * (当设置为wrap_content时,模式为AT_MOST, 表示子view的大小最多是多少,这样子view会根据这个上限来设置自己的尺寸) */ if (mode == MeasureSpec.AT_MOST) { if (isWidth) { result = Math.max(result, size); } else { result = Math.min(result, size); } } } return result; } @Override protected void onDraw(Canvas canvas) { //如果要绘制当前进度值文本 if (mIfDrawText) { calculateDrawRectF(); }else { calculateDrawRectFWithoutProgressText(); } //如果要绘制当前进度值之前的进度条 if (mDrawReachedBar) { canvas.drawRect(mReachedRectF, mReachedBarPaint); } //如果要绘制当前进度值之后的进度条 if (mDrawUnreachedBar) { canvas.drawRect(mUnreachedRectF, mUnreachedBarPaint); } //绘制当前进度值文本 if (mIfDrawText) canvas.drawText(mCurrentDrawText, mDrawTextStart, mDrawTextEnd, mTextPaint); } /** * 初始化画笔 */ private void initializePainters() { mReachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mReachedBarPaint.setColor(mReachedBarColor); mUnreachedBarPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mUnreachedBarPaint.setColor(mUnreachedBarColor); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setColor(mTextColor); mTextPaint.setTextSize(mTextSize); } /** * 计算不要绘制当前进度值文本时 图形的各个属性 */ private void calculateDrawRectFWithoutProgressText() { //当前进度值不画 //当前进度值之前的进度条(长方形)的属性 mReachedRectF.left = getPaddingLeft(); mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f; mReachedRectF.right = (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() + getPaddingLeft(); mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f; //当前进度值之后的进度条(长方形)的属性 mUnreachedRectF.left = mReachedRectF.right; mUnreachedRectF.right = getWidth() - getPaddingRight(); mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f; mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f; } /** * 计算要绘制当前进度值文本时 图形的各个属性 */ private void calculateDrawRectF() { //要绘制的当前进度值的文本 mCurrentDrawText = String.format("%d", getProgress() * 100 / getMax()); mCurrentDrawText = mPrefix + mCurrentDrawText + mSuffix; //要绘制的当前进度值的文本的宽度 mDrawTextWidth = mTextPaint.measureText(mCurrentDrawText); //如果当前进度值为0,则不绘制当前进度值之前的进度条 if (getProgress() == 0) { mDrawReachedBar = false; mDrawTextStart = getPaddingLeft(); } //否则绘制当前进度值文本之前的进度条 else { mDrawReachedBar = true; //当前进度值文本之前的进度条(长方形)的属性 mReachedRectF.left = getPaddingLeft(); mReachedRectF.top = getHeight() / 2.0f - mReachedBarHeight / 2.0f; mReachedRectF.right= (getWidth() - getPaddingLeft() - getPaddingRight()) / (getMax() * 1.0f) * getProgress() - mOffset + getPaddingLeft(); mReachedRectF.bottom = getHeight() / 2.0f + mReachedBarHeight / 2.0f; //当前进度值的文本的起始位置 mDrawTextStart = (mReachedRectF.right + mOffset); } //当前进度值的文本的结束位置 mDrawTextEnd = (int) ((getHeight() / 2.0f) - ((mTextPaint.descent() + mTextPaint.ascent()) / 2.0f)); //如果画不下当前进度值的文本了,就重新计算下当前进度值的文本的起始位置和当前进度值之前的进度条(长方形)的右边 if ((mDrawTextStart + mDrawTextWidth) >= getWidth() - getPaddingRight()) { mDrawTextStart = getWidth() - getPaddingRight() - mDrawTextWidth; mReachedRectF.right = mDrawTextStart - mOffset; } //当前进度值文本之后的进度条的起始位置 float unreachedBarStart = mDrawTextStart + mDrawTextWidth + mOffset; //如果画不下进度值文本之后的进度条了,就不画进度值之后的进度条 if (unreachedBarStart >= getWidth() - getPaddingRight()) { mDrawUnreachedBar = false; } else { mDrawUnreachedBar = true; //当前进度值文本之后的进度条(长方形)的属性 mUnreachedRectF.left = unreachedBarStart; mUnreachedRectF.right = getWidth() - getPaddingRight(); mUnreachedRectF.top = getHeight() / 2.0f + -mUnreachedBarHeight / 2.0f; mUnreachedRectF.bottom = getHeight() / 2.0f + mUnreachedBarHeight / 2.0f; } } /** * Get progress text color. * 获取当前进度值文本的颜色 * @return progress text color. */ public int getTextColor() { return mTextColor; } /** * Get progress text size. * 获取当前进度值文本的字体大小 * @return progress text size. */ public float getProgressTextSize() { return mTextSize; } /** * 获取当前进度值文本之后的进度条颜色 */ public int getUnreachedBarColor() { return mUnreachedBarColor; } /** * 获取当前进度值文本之前的进度条颜色 */ public int getReachedBarColor() { return mReachedBarColor; } /** * 获取进度条的当前进度值 */ public int getProgress() { return mCurrentProgress; } /** * 获取进度条的最大值 */ public int getMax() { return mMaxProgress; } /** * 获取当前进度值文本之前的进度条的高度 */ public float getReachedBarHeight() { return mReachedBarHeight; } /** * 获取当前进度值文本之后的进度条的高度 */ public float getUnreachedBarHeight() { return mUnreachedBarHeight; } /** * 设置当前进度值文本的字体大小 * @param textSize 当前进度值文本的字体大小 */ public void setProgressTextSize(float textSize) { this.mTextSize = textSize; mTextPaint.setTextSize(mTextSize); invalidate(); } /** * 设置当前进度值文本的颜色 * @param textColor 当前进度值文本的颜色 */ public void setProgressTextColor(int textColor) { this.mTextColor = textColor; mTextPaint.setColor(mTextColor); invalidate(); } /** * 设置当前进度值文本之后的进度条颜色 * @param barColor 当前进度值文本之后的进度条颜色 */ public void setUnreachedBarColor(int barColor) { this.mUnreachedBarColor = barColor; mUnreachedBarPaint.setColor(mUnreachedBarColor); invalidate(); } /** * 设置当前进度值文本之前的进度条颜色 * @param progressColor 当前进度值文本之前的进度条颜色 */ public void setReachedBarColor(int progressColor) { this.mReachedBarColor = progressColor; mReachedBarPaint.setColor(mReachedBarColor); invalidate(); } /** * 设置当前进度值文本之前的进度条的高度 * @param height 当前进度值文本之前的进度条的高度 */ public void setReachedBarHeight(float height) { mReachedBarHeight = height; } /** * 设置当前进度值文本之后的进度条的高度 * @param height 当前进度值文本之后的进度条的高度 */ public void setUnreachedBarHeight(float height) { mUnreachedBarHeight = height; } /** * 设置进度值的最大值 * @param maxProgress 进度值的最大值 */ public void setMax(int maxProgress) { if (maxProgress > 0) { this.mMaxProgress = maxProgress; invalidate(); } } /** * 设置当前进度值文本的后缀 * @param suffix 当前进度值文本的后缀 */ public void setSuffix(String suffix) { if (suffix == null) { mSuffix = ""; } else { mSuffix = suffix; } } /** * 获取当前进度值文本的后缀 */ public String getSuffix() { return mSuffix; } /** * 设置当前进度值文本的前缀 * @param prefix 当前进度值文本的前缀 */ public void setPrefix(String prefix) { if (prefix == null) mPrefix = ""; else { mPrefix = prefix; } } /** * 获取当前进度值文本的前缀 */ public String getPrefix() { return mPrefix; } /** * 设置进度条的当前进度值增加 * @param by 增加多少 */ public void incrementProgressBy(int by) { if (by > 0) { setProgress(getProgress() + by); } if (mListener != null) { //回调onProgressChange()方法来处理进度值变化后的事件 mListener.onProgressChange(getProgress(), getMax()); } } /** * 设置当前进度值 * * @param progress 当前进度值 */ public void setProgress(int progress) { if (progress <= getMax() && progress >= 0) { this.mCurrentProgress = progress; invalidate(); } } @Override protected Parcelable onSaveInstanceState() { final Bundle bundle = new Bundle(); bundle.putParcelable(INSTANCE_STATE, super.onSaveInstanceState()); bundle.putInt(INSTANCE_TEXT_COLOR, getTextColor()); bundle.putFloat(INSTANCE_TEXT_SIZE, getProgressTextSize()); bundle.putFloat(INSTANCE_REACHED_BAR_HEIGHT, getReachedBarHeight()); bundle.putFloat(INSTANCE_UNREACHED_BAR_HEIGHT, getUnreachedBarHeight()); bundle.putInt(INSTANCE_REACHED_BAR_COLOR, getReachedBarColor()); bundle.putInt(INSTANCE_UNREACHED_BAR_COLOR, getUnreachedBarColor()); bundle.putInt(INSTANCE_MAX, getMax()); bundle.putInt(INSTANCE_PROGRESS, getProgress()); bundle.putString(INSTANCE_SUFFIX, getSuffix()); bundle.putString(INSTANCE_PREFIX, getPrefix()); bundle.putBoolean(INSTANCE_TEXT_VISIBILITY, getProgressTextVisibility()); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if (state instanceof Bundle) { final Bundle bundle = (Bundle) state; mTextColor = bundle.getInt(INSTANCE_TEXT_COLOR); mTextSize = bundle.getFloat(INSTANCE_TEXT_SIZE); mReachedBarHeight = bundle.getFloat(INSTANCE_REACHED_BAR_HEIGHT); mUnreachedBarHeight = bundle.getFloat(INSTANCE_UNREACHED_BAR_HEIGHT); mReachedBarColor = bundle.getInt(INSTANCE_REACHED_BAR_COLOR); mUnreachedBarColor = bundle.getInt(INSTANCE_UNREACHED_BAR_COLOR); initializePainters(); setMax(bundle.getInt(INSTANCE_MAX)); setProgress(bundle.getInt(INSTANCE_PROGRESS)); setPrefix(bundle.getString(INSTANCE_PREFIX)); setSuffix(bundle.getString(INSTANCE_SUFFIX)); setProgressTextVisibility(bundle.getBoolean(INSTANCE_TEXT_VISIBILITY) ? Visible : Invisible); super.onRestoreInstanceState(bundle.getParcelable(INSTANCE_STATE)); return; } super.onRestoreInstanceState(state); } /** * dp转px */ public float dp2px(float dp) { final float scale = getResources().getDisplayMetrics().density; return dp * scale + 0.5f; } /** * sp转px */ public float sp2px(float sp) { final float scale = getResources().getDisplayMetrics().scaledDensity; return sp * scale; } /** * 设置是否绘制当前进度值文本 */ public void setProgressTextVisibility(ProgressTextVisibility visibility) { mIfDrawText = visibility == Visible; invalidate(); } /** * 获取是否绘制当前进度值文本 */ public boolean getProgressTextVisibility() { return mIfDrawText; } /** * 设置进度值变化时的监听器 */ public void setOnProgressBarListener(OnProgressBarListener listener) { mListener = listener; } }

如以上代码所示:

在自定义NumberProgressBar控件的构造方法中,去获取了全部设置好了的自定义属性值,如果没有设置则使用默认的自定义属性值。

然后先重写onMeasure(int widthMeasureSpec, int heightMeasureSpec)方法,来确定自定义NumberProgressBar控件的大小。

接着重写onDraw()方法,进行绘制自定义的带数字的进度条。

第三步、将自定义带数字的进度条添加到布局文件中

在res/layout目录下定义一个activity_main.xml文件,res/layout/activity_main.xml定义代码如下所示:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:custom="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.daimajia.numberprogressbar.example.MainActivity="> <com.daimajia.numberprogressbar.NumberProgressBar android:id="@+id/numberbar1" android:layout_width="wrap_content" android:padding="20dp" custom:progress_current="0" style="@style/NumberProgressBar_Default" android:layout_height="wrap_content" /> <com.daimajia.numberprogressbar.NumberProgressBar android:id="@+id/numberbar2" android:layout_height="wrap_content" android:padding="20dp" custom:progress_current="20" android:layout_width="match_parent" style="@style/NumberProgressBar_Passing_Green" /> <com.daimajia.numberprogressbar.NumberProgressBar android:id="@+id/numberbar3" android:layout_margin="20dp" style="@style/NumberProgressBar_Relax_Blue" custom:progress_current="30" android:layout_height="wrap_content" /> <com.daimajia.numberprogressbar.NumberProgressBar android:id="@+id/numberbar4" android:layout_width="wrap_content" android:layout_margin="20dp" style="@style/NumberProgressBar_Grace_Yellow" custom:progress_current="40" android:layout_height="wrap_content" /> <com.daimajia.numberprogressbar.NumberProgressBar android:id="@+id/numberbar5" android:layout_width="wrap_content" android:layout_margin="20dp" custom:progress_current="50" style="@style/NumberProgressBar_Warning_Red" android:layout_height="wrap_content" /> <com.daimajia.numberprogressbar.NumberProgressBar android:id="@+id/numberbar6" android:layout_width="wrap_content" android:layout_margin="20dp" style="@style/NumberProgressBar_Funny_Orange" custom:progress_current="60" android:layout_height="wrap_content" /> <com.daimajia.numberprogressbar.NumberProgressBar android:id="@+id/numberbar7" android:layout_width="wrap_content" android:layout_margin="20dp" style="@style/NumberProgressBar_Beauty_Red" custom:progress_current="70" android:layout_height="wrap_content" /> <com.daimajia.numberprogressbar.NumberProgressBar android:id="@+id/numberbar8" android:layout_width="wrap_content" android:layout_margin="20dp" style="@style/NumberProgressBar_Twinkle_Night" custom:progress_current="80" android:layout_height="wrap_content" /> <com.daimajia.numberprogressbar.NumberProgressBar android:id="@+id/numberbar9" android:layout_width="wrap_content" android:layout_margin="20dp" custom:progress_current="20" custom:progress_max="100" custom:progress_unreached_color="#FF530D" custom:progress_reached_color="#6DBCDB" custom:progress_text_size="10sp" custom:progress_text_color="#ECF0F1" custom:progress_reached_bar_height="1.5dp" custom:progress_unreached_bar_height="0.75dp" android:layout_height="wrap_content" /> </LinearLayout>

第四步、编写Activity加载布局文件,显示自定义的带数字的进度条

MainActity的代码如下所示:

package com.daimajia.numberprogressbar.example; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.widget.Toast; import com.daimajia.numberprogressbar.NumberProgressBar; import com.daimajia.numberprogressbar.OnProgressBarListener; import java.util.Timer; import java.util.TimerTask; public class MainActivity extends Activity implements OnProgressBarListener { private Timer timer; private NumberProgressBar bnp; private NumberProgressBar bnp9; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bnp = (NumberProgressBar)findViewById(R.id.numberbar1); bnp.setOnProgressBarListener(this); bnp9 = (NumberProgressBar)findViewById(R.id.numberbar9); bnp9.setPrefix("欧阳鹏:"); bnp9.setSuffix("% CSDN"); bnp9.setProgressTextSize(20); bnp9.setProgressTextColor(Color.YELLOW); bnp9.setProgressTextVisibility(NumberProgressBar.ProgressTextVisibility.Visible); bnp9.setUnreachedBarColor(Color.RED); bnp9.setReachedBarHeight(10); bnp9.setReachedBarHeight(5); timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { bnp.incrementProgressBy(1); } }); } }, 1000, 100); } @Override protected void onDestroy() { super.onDestroy(); timer.cancel(); } @Override public void onProgressChange(int current, int max) { if(current == max) { Toast.makeText(getApplicationContext(), getString(R.string.finish), Toast.LENGTH_SHORT).show(); bnp.setProgress(0); } } }

显示出的效果图为:

看完介绍后,读者可以到以下地址去查看完整的项目代码

daimajia的github上该项目的原始地址

https://github.com/daimajia/NumberProgressBar

这里还有另外一个NumberProgresBar的例子,如下图所示

以上内容是小编给大家介绍的Android自定义View实现带数字的进度条实例代码,希望对大家有所帮助!

时间: 2024-12-22 12:51:05

Android自定义View实现带数字的进度条实例代码的相关文章

Android自定义View实现带数字的进度条实例代码_Android

第一步.效果展示 图1.蓝色的进度条 图2.红色的进度条 图3.多条颜色不同的进度条 图4.多条颜色不同的进度条 第二步.自定义ProgressBar实现带数字的进度条 0.项目结构 如上图所示:library项目为自定义的带数字的进度条NumberProgressBar的具体实现,demo项目为示例项目以工程依赖的方式引用library项目,然后使用自定义的带数字的进度条NumberProgressBar来做展示   如上图所示:自定义的带数字的进度条的library项目的结构图   如上图所

我的Android进阶之旅------&amp;gt;Android自定义View实现带数字的进度条(NumberProgressBar)

今天在Github上面看到一个来自于 daimajia所写的关于Android自定义View实现带数字的进度条(NumberProgressBar)的精彩案例,在这里分享给大家一起来学习学习!同时感谢daimajia的开源奉献! 第一步.效果展示 图1.蓝色的进度条 图2.红色的进度条 图3.多条颜色不同的进度条 图4.多条颜色不同的进度条 版权声明:本文为[欧阳鹏]原创文章,欢迎转载,转载请注明出处! [http://blog.csdn.net/ouyang_peng/article/deta

jQuery多文件异步上传带进度条实例代码_jquery

先给大家展示下效果图: ///作者:柯锦 ///完成时间:2016.08.16 ///多文件异步上传带进度条 (function ($) { function bytesToSize(bytes) { if (bytes === 0) return '0 B'; var k = 1024, // or 1000 sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], i = Math.floor(Math.log(bytes)

Android仿泡泡窗实现下拉菜单条实例代码

功能描述:点击下拉按钮,显示出所有的条目,有删除和点击功能,点击后将条目显示. 注意:泡泡窗默认是没有焦点的.要让泡泡窗获取到焦点.假如listview的item中有Button,ImageButton,CheckBox等会强制获取焦点的view 此时,listview的item无法获取焦点,从而无法被点击 解决方法:给item的根布局增加以下属性 Android:descendantFocusability="blocksDescendants"设置之后,Button获取焦点,ite

Android自定义View仿QQ等级天数进度

最近一直都在看自定义View这一块.差不多一个星期了吧.这个星期坚持每天更新博客,感觉自己的技术也有点突破,对自定义View的计算也有了更深的认识. 今天看到手机一个成长天数进度的控件,觉得挺有意思的,于是想自己也写一个.效果如下: 由图可以知道,这里面有很多个元素,首先是背景的矩形区域,其次就是两个环形,然后三个Text文本.其实不复杂,我们一点一点的去实现. 首先呢,画矩形背景.这里用到一个RectF的类,这个类包含一个矩形的四个单精度浮点坐标.矩形通过上下左右4个边的坐标来表示一个矩形.这

自定义View,又一种进度条的呈现,CircleProgressView使用解析

转载请注明出处王亟亟的大牛之路 话不多说,先上效果图 循环旋转的状态 项目结构 一个Sample包,一个Lib包.Lib包里面其实只有一个累,很多内容都在素材文件里,比较建议把内容复制出来,贴到自己的项目中 主类: public class MainActivity extends ActionBarActivity { CircleProgressView mCircleView; Switch mSwitchSpin; Switch mSwitchShowUnit; SeekBar mSee

asp.net web大文件上传带进度条实例代码_实用技巧

复制代码 代码如下: using System; using System.Data; using System.Configuration; using System.Collections; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using Syste

Android自定义view圆并随手指移动

本文实例为大家分享了Android自定义view圆并随手指移动的具体代码,供大家参考,具体内容如下 main代码 public class MainActivity extends AppCompatActivity { private int screenW; //屏幕宽度 private int screenH; //屏幕高度 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(saved

Android自定义View之使用贝塞尔曲线实现流量进度条

第一次写带图片的博客,多少还是有点紧张,效果不好,请将就着看,前面的图是今天要写的控件的效果图,元素不多,分别是一个按钮和一个自定义的控件. 在此以前,我看过许多的书,比如<Android群英传>.<第一行代码>等,也看了很多大神的博客,但是即便是这样,当我看到这么多代码的时候,一直都没有真正的动手去敲过这些代码,以至于我总是觉得自定义View是一个多么高深莫测的技术,我们这些小白是难以触及的,但是当昨晚看了一篇鸡汤之后,觉得人还是要学会专注,要耐得住寂寞,要沉得住气.所以在未来的