android 自定义进度条

来源:互联网 发布:淘宝刷收藏怎么算的 编辑:程序博客网 时间:2024/06/08 11:21

效果图:


入口MainActivity

package com.beyole.definedprogressbar;import com.beyole.view.HorizontalProgressbarWithNumbers;import android.app.Activity;import android.os.Bundle;import android.os.Handler;public class MainActivity extends Activity {private HorizontalProgressbarWithNumbers mProgressBar;private static final int PROGRESS_UPDATE = 0x111;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mProgressBar = (HorizontalProgressbarWithNumbers) findViewById(R.id.id_myHorizontalProgressBar);MyHandler.sendEmptyMessage(PROGRESS_UPDATE);}private Handler MyHandler = new Handler() {public void handleMessage(android.os.Message msg) {int progress = mProgressBar.getProgress();mProgressBar.setProgress(++progress);if (progress > 100) {MyHandler.removeMessages(PROGRESS_UPDATE);}MyHandler.sendEmptyMessageDelayed(PROGRESS_UPDATE, 100);};};}

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:beyole="http://schemas.android.com/apk/res/com.beyole.definedprogressbar"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <com.beyole.view.HorizontalProgressbarWithNumbers        android:id="@+id/id_myHorizontalProgressBar"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="50dip"        android:padding="5dp" >    </com.beyole.view.HorizontalProgressbarWithNumbers>    <com.beyole.view.RoundProgressbarWithNumbers        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="50dip"        android:padding="5dp"        android:progress="50"        beyole:process_reached_bar_height="20dp"        beyole:process_text_color="#ffF53B03"        beyole:radius="60dp" /></LinearLayout>



HorizontalProgressbarWithNumbers.java

package com.beyole.view;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.ProgressBar;import com.beyole.definedprogressbar.R;public class HorizontalProgressbarWithNumbers extends ProgressBar {// 设置默认字体大小private static final int DEFAULT_TEXT_SIZE = 10;// 设置默认字体的颜色private static final int DEFAULT_TEXT_COLOR = 0XFFFC00D1;// 设置默认未处理完的进度条的颜色private static final int DEFAULT_PROCESS_UNREACHED_COLOR = 0XFFD3D6DA;// 设置默认正在运行的进度条的高度private static final int DEFAULT_PROCESS_UNREACHED_BAR_HEIGHT = 2;// 设置默认还未进行的进度条的高度private static final int DEFAULT_PROCESS_REACHED_BAR_HEIGHT = 2;// 设置默认的字体与正在运行的进度条的偏移private static final int DEFAULT_PROCESS_TEXT_OFFSET = 10;// 画笔protected Paint mPaint = new Paint();// 字体颜色protected int mTextColor = DEFAULT_TEXT_COLOR;// 字体大小 sp转换为pxprotected int mTextSize = sp2px(DEFAULT_TEXT_SIZE);// 字体偏移 dp转换为pxprotected int mTextOffset = dp2px(DEFAULT_PROCESS_TEXT_OFFSET);// 未在运行的进度条的高度protected int mProcessUnreachedBarHeight = dp2px(DEFAULT_PROCESS_UNREACHED_BAR_HEIGHT);// 正在运行的进度条的高度protected int mProcessReachedBarHeight = dp2px(DEFAULT_PROCESS_REACHED_BAR_HEIGHT);// 设置正在运行的进度条的颜色protected int mReachedBarColor = DEFAULT_TEXT_COLOR;// 设置未运行的进度条的颜色protected int mUnreachedBarColor = DEFAULT_PROCESS_UNREACHED_COLOR;// 进度条宽度protected int mRealWidth;// 是否显示文字进度protected boolean mIfDrawtext = true;// 是否可见protected static final int VISIBLE = 0;public HorizontalProgressbarWithNumbers(Context context) {this(context, null);}public HorizontalProgressbarWithNumbers(Context context, AttributeSet attrs) {this(context, attrs, 0);}public HorizontalProgressbarWithNumbers(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);setHorizontalScrollBarEnabled(true);obtainStyledAttributeSet(attrs);mPaint.setColor(mTextColor);mPaint.setTextSize(mTextSize);}/** * 获取xml中设置好的属性 *  * @param attrs */private void obtainStyledAttributeSet(AttributeSet attrs) {TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.HorizontalProgressbarWithNumbers);mTextColor = typedArray.getColor(R.styleable.HorizontalProgressbarWithNumbers_process_text_color, DEFAULT_TEXT_COLOR);mTextSize = (int) typedArray.getDimension(R.styleable.HorizontalProgressbarWithNumbers_process_text_size, mTextSize);mReachedBarColor = typedArray.getColor(R.styleable.HorizontalProgressbarWithNumbers_process_reached_color, mTextColor);mUnreachedBarColor = typedArray.getColor(R.styleable.HorizontalProgressbarWithNumbers_process_unreached_color, DEFAULT_PROCESS_UNREACHED_COLOR);mProcessReachedBarHeight = (int) typedArray.getDimension(R.styleable.HorizontalProgressbarWithNumbers_process_reached_bar_height, DEFAULT_PROCESS_REACHED_BAR_HEIGHT);mProcessUnreachedBarHeight = (int) typedArray.getDimension(R.styleable.HorizontalProgressbarWithNumbers_process_unreached_bar_height, DEFAULT_PROCESS_UNREACHED_BAR_HEIGHT);mTextOffset = typedArray.getInt(R.styleable.HorizontalProgressbarWithNumbers_process_text_offset, DEFAULT_PROCESS_TEXT_OFFSET);int textVisible = typedArray.getInt(R.styleable.HorizontalProgressbarWithNumbers_process_text_visibility, VISIBLE);if (textVisible != VISIBLE) {mIfDrawtext = false;}typedArray.recycle();}/** * 所有的属性,包括进度条的宽度都是由用户自定义的,所以需要重新测量一下view的大小 */@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int heightMode = MeasureSpec.getMode(heightMeasureSpec);// 如果宽度模式为wrap_content,则进行测量if (heightMode != MeasureSpec.EXACTLY) {float textHeight = mPaint.ascent() + mPaint.descent();int exceptHeight = (int) (getPaddingTop() + getPaddingBottom() + Math.max(Math.max(mProcessReachedBarHeight, mProcessUnreachedBarHeight), Math.abs(textHeight)));// 重新设置宽度heightMeasureSpec = MeasureSpec.makeMeasureSpec(exceptHeight, MeasureSpec.EXACTLY);}super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected synchronized void onDraw(Canvas canvas) {// 保存当前画布canvas.save();// 画笔平移到getPaddingLeft(),getHeight/2。以此为坐标原点(0,0)canvas.translate(getPaddingLeft(), getHeight() / 2);boolean noNeedBg = false;// 当前进度与最大值的比率float ratio = getProgress() * 1.0f / getMax();// 已到达的宽度float processPosX = ratio * mRealWidth;// 绘制的文本String text = getProgress() + "%";// 拿到字体的宽度和高度float textWidth = mPaint.measureText(text);float textHeight = (mPaint.ascent() + mPaint.descent()) / 2;// 如果到达最后,则未进行的部分不用绘制if (processPosX + textWidth > mRealWidth) {processPosX = mRealWidth - textWidth;noNeedBg = true;}// 绘制到达的进度float endX = processPosX - mTextOffset / 2;if (endX > 0) {mPaint.setColor(mReachedBarColor);mPaint.setStrokeWidth(mProcessReachedBarHeight);canvas.drawLine(0, 0, endX, 0, mPaint);}// 绘制文本if (mIfDrawtext) {mPaint.setColor(mTextColor);canvas.drawText(text, processPosX, -textHeight, mPaint);}// 绘制未到达的进度if (!noNeedBg) {float start = processPosX + textWidth + mTextOffset / 2;mPaint.setColor(mUnreachedBarColor);mPaint.setStrokeWidth(mProcessUnreachedBarHeight);canvas.drawLine(start, 0, mRealWidth, 0, mPaint);}canvas.restore();}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);mRealWidth = w - getPaddingLeft() - getPaddingRight();}/** * dp转换为px *  * @param dpVal * @return */public int dp2px(int dpVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpVal, getResources().getDisplayMetrics());}/** * sp转换为px *  * @param spVal * @return */public int sp2px(int spVal) {return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spVal, getResources().getDisplayMetrics());}}
RoundProgressbarWithNumbers.java
package com.beyole.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Paint.Cap;import android.graphics.Paint.Style;import android.graphics.RectF;import android.util.AttributeSet;import com.beyole.definedprogressbar.R;public class RoundProgressbarWithNumbers extends HorizontalProgressbarWithNumbers {private int mRadius = dp2px(30);public RoundProgressbarWithNumbers(Context context) {this(context, null);}public RoundProgressbarWithNumbers(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RoundProgressbarWithNumbers(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);mProcessReachedBarHeight = (int) (mProcessUnreachedBarHeight * 2.5f);TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundProgressbarWithNumbers);mRadius = (int) typedArray.getDimension(R.styleable.RoundProgressbarWithNumbers_radius, mRadius);typedArray.recycle();mTextSize = sp2px(14);mPaint.setStyle(Style.STROKE);// 画笔类型 STROKE空心 FILL 实心 FILL_AND_STROKE// 用契形填充mPaint.setAntiAlias(true); // 防锯齿mPaint.setDither(true);// 防抖动mPaint.setStrokeCap(Cap.ROUND);// //画笔笔刷类型 如影响画笔但始末端}@Overrideprotected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int paintWidth = Math.max(mProcessReachedBarHeight, mProcessUnreachedBarHeight);if (heightMode != MeasureSpec.EXACTLY) {int exceptHeight = getPaddingTop() + getPaddingBottom() + paintWidth + mRadius * 2;heightMeasureSpec = MeasureSpec.makeMeasureSpec(exceptHeight, MeasureSpec.EXACTLY);}if (widthMode != MeasureSpec.EXACTLY) {int exceptWidth = getPaddingLeft() + getPaddingRight() + mRadius * 2 + paintWidth;widthMeasureSpec = MeasureSpec.makeMeasureSpec(exceptWidth, MeasureSpec.EXACTLY);}super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected synchronized void onDraw(Canvas canvas) {String progress = getProgress() + "%";float textWidth = mPaint.measureText(progress);float textHeight = (mPaint.ascent() + mPaint.descent()) / 2;canvas.save();canvas.translate(getPaddingLeft(), getPaddingTop());mPaint.setStyle(Style.STROKE);mPaint.setColor(mUnreachedBarColor);mPaint.setStrokeWidth(mProcessUnreachedBarHeight);canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);mPaint.setColor(mReachedBarColor);mPaint.setStrokeWidth(mProcessReachedBarHeight);float sweepAngle = getProgress() * 1.0f / getMax() * 360;canvas.drawArc(new RectF(0, 0, mRadius * 2, mRadius * 2), 0, sweepAngle, false, mPaint);mPaint.setStyle(Style.FILL);canvas.drawText(progress, mRadius - textWidth / 2, mRadius - textHeight, mPaint);canvas.restore();}}
attrs.xml

<?xml version="1.0" encoding="utf-8"?><resources>    <declare-styleable name="HorizontalProgressbarWithNumbers">        <attr name="process_unreached_color" format="color" />        <attr name="process_reached_color" format="color" />        <attr name="process_unreached_bar_height" format="dimension" />        <attr name="process_reached_bar_height" format="dimension" />        <attr name="process_text_size" format="dimension" />        <attr name="process_text_color" format="color" />        <attr name="process_text_offset" format="dimension" />        <attr name="process_text_visibility" format="enum">            <enum name="visible" value="0" />            <enum name="invisiable" value="1" />        </attr>    </declare-styleable>    <declare-styleable name="RoundProgressbarWithNumbers">        <attr name="radius" format="dimension" />    </declare-styleable></resources>



0 0