Android 自定义的圆形变化ProgressBar

来源:互联网 发布:淘宝海报图片 编辑:程序博客网 时间:2024/04/27 13:54

Android 自带的ProgressBar中大多比较丑,所以自己定制了一个ProgressBar,可以实现动态的播放,先看截图

然后上代码,^_^原谅我不会说别的。

先看主程序布局文件

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:background="@color/simple_bg"    tools:context=".MainActivity" >    <lib.vgod.progresscicle.library.DashProgressBar         android:id="@+id/simple"        custom:external_color="#1affffff"        custom:base_color="#6effffff"        custom:min="0"        custom:max="999"        custom:progress_color="#000000"        custom:progress_icon="@drawable/star"        custom:duration="1500"        android:layout_centerInParent="true"        android:layout_width="300dp"        android:layout_height="300dp">        <RelativeLayout            android:layout_centerInParent="true"            android:layout_width="wrap_content"            android:layout_height="wrap_content">            <TextView                android:textSize="25sp"                android:id="@+id/text"                android:textColor="#000000"                android:text="@string/stars"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />            <TextView                android:textSize="30sp"                android:layout_centerHorizontal="true"                android:id="@+id/number"                android:paddingTop="5dp"                android:layout_below="@+id/text"                android:textColor="#000000"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />        </RelativeLayout>            </lib.vgod.progresscicle.library.DashProgressBar>        <Button         android:id="@+id/start"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@id/simple"        android:layout_alignParentLeft="true"        android:text="@string/start"/>        <Button         android:id="@+id/restart"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_below="@id/simple"        android:layout_toRightOf="@id/start"        android:text="@string/restart"/></RelativeLayout>
然后主程序

package lib.vgod.progresscicle;import lib.vgod.progresscicle.library.DashProgressBar;import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;import android.widget.Button;public class MainActivity extends Activity {DashProgressBar dashProgressBar;Button startBtn;Button restartBtn;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        dashProgressBar = (DashProgressBar)findViewById(R.id.simple);        startBtn = (Button)findViewById(R.id.start);        restartBtn = (Button)findViewById(R.id.restart);                startBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {dashProgressBar.startAnimate();}});                restartBtn.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View arg0) {dashProgressBar.restartAnimate();}});    }    @Override    public boolean onCreateOptionsMenu(Menu menu) {        // Inflate the menu; this adds items to the action bar if it is present.        getMenuInflater().inflate(R.menu.main, menu);        return true;    }    }

这里我自定义了一个绘制板,包括draw(),onSizeChanged()主要是方便在View中draw方法和onSizeChanged调用

package lib.vgod.progresscicle.library;import android.graphics.Canvas;/** * @author niuwei * */public interface Painter {void draw(Canvas canvas);void onSizeChanged(int width, int height);void setColor(int color);int getColor();}
然后是绘制外部圆圈的绘制板

package lib.vgod.progresscicle.library;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.RectF;public class ExternalCirclePainter implements Painter{private Paint externalPainter;private RectF externalCircle;private int color;//颜色    private int externalStrokeWidth = 4;//椭圆宽度    private int startAngle = 279;//开始角度    private int finishAngle = 341;//结束角度    private int width;//宽    private int height;//高    private float marginTop = 11;//上边距    /**     * 初始构造器,构造外部圆圈画笔的颜色     * @param externalColor     */    public ExternalCirclePainter(int externalColor) {        this.color = externalColor;        init();    }    /**     * 初始化     */    private void init() {        initExternalCirclePainter();    }    /**     * 初始化画笔     */    private void initExternalCirclePainter() {    externalPainter = new Paint();    externalPainter.setAntiAlias(true);    externalPainter.setStrokeWidth(externalStrokeWidth);        externalPainter.setColor(color);        externalPainter.setStyle(Paint.Style.STROKE);    }    /**     * 初始化圆圈的大小     */    private void initExternalCircle() {        externalCircle = new RectF();        externalCircle.set(externalStrokeWidth, externalStrokeWidth * marginTop,                width - externalStrokeWidth, height - externalStrokeWidth);    }    @Overridepublic void draw(Canvas canvas) {canvas.drawArc(externalCircle, startAngle, finishAngle, false, externalPainter);}@Overridepublic void onSizeChanged(int width, int height) {this.width = width;this.height = height;initExternalCircle();}@Overridepublic void setColor(int color) {this.color = color;}@Overridepublic int getColor() {return color;}}

绘制内部dash圆圈的绘制板,其实主要起作用的是
<span style="color:#ff0000;">internalCirclePaint.setPathEffect(new DashPathEffect(new float[]{dashWidth, dashSpace}, dashSpace));</span>

package lib.vgod.progresscicle.library;import android.graphics.Canvas;import android.graphics.DashPathEffect;import android.graphics.Paint;import android.graphics.RectF;public class InternalCirclePainter implements Painter{private RectF internalCircle;    private Paint internalCirclePaint;    private int color;    private float startAngle = 270;    private float finishAngle = 359.8f;    private int width;    private int height;    private int internalStrokeWidth = 48;    private int dashWidth = 5;    private int dashSpace = 8;    private float marginTop = 45;    /**     * 初始构造器,构造外部圆圈画笔的颜色     * @param externalColor     */    public InternalCirclePainter(int externalColor) {        this.color = externalColor;        init();    }    /**     * 初始化     */    private void init() {    initInternalCirclePainter();    }        /**     * 初始化绘制圆圈的画笔     */    private void initInternalCirclePainter(){    internalCirclePaint = new Paint();    internalCirclePaint.setAntiAlias(true);    internalCirclePaint.setStrokeWidth(internalStrokeWidth);    internalCirclePaint.setColor(color);        internalCirclePaint.setStyle(Paint.Style.STROKE);        internalCirclePaint.setPathEffect(new DashPathEffect(new float[]{dashWidth, dashSpace}, dashSpace));    }        /**     * 初始化内部圆圈的大小     */    private void initInternalCircle(){    internalCircle = new RectF();    float padding = internalStrokeWidth * 1.7f;    internalCircle.set(padding, padding + marginTop, width - padding, height - padding);    }    @Overridepublic void draw(Canvas canvas) {canvas.drawArc(internalCircle, startAngle, finishAngle, false, internalCirclePaint);}@Overridepublic void onSizeChanged(int width, int height) {this.width = width;        this.height = height;        initInternalCircle();}@Overridepublic void setColor(int color) {this.color = color;internalCirclePaint.setColor(this.color);}@Overridepublic int getColor() {return this.color;}}

然后是可变化的dash圆圈的接口

package lib.vgod.progresscicle.library;/** * @author niuwei * */public interface ProgressPainter extends Painter{void setMax(float max);    void setMin(float min);    void setValue(float value);}

可变化的绘制圆圈类

package lib.vgod.progresscicle.library;import android.graphics.Canvas;import android.graphics.DashPathEffect;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.RectF;/** * @author niuwei * */public class ProgressPainterImp implements ProgressPainter{private float min;private float max;private int mColor;private Paint mPaint;private RectF progressCircle;private float startAngle = 270f;    private float plusAngle = 0;private int width;    private int height;    private int internalStrokeWidth = 48;    private int dashWidth = 5;    private int dashSpace = 8;    private float marginTop = 45;    private float padding;    public ProgressPainterImp(int color, float min, float max){    mColor = color;    this.min = min;    this.max = max;    init();    }        private void init(){    initInternalCirclePainter();    }        private void initInternalCirclePainter() {    mPaint = new Paint();    mPaint.setAntiAlias(true);    mPaint.setColor(mColor);    mPaint.setStrokeWidth(internalStrokeWidth);    mPaint.setStyle(Style.STROKE);    mPaint.setPathEffect(new DashPathEffect(new float[]{dashWidth, dashSpace}, dashSpace));    }        private void initInternalCircle() {    progressCircle = new RectF();        padding = internalStrokeWidth * 1.7f;        progressCircle.set(padding, padding + marginTop, width - padding, height - padding);    }    @Overridepublic void draw(Canvas canvas) {canvas.drawArc(progressCircle, startAngle, plusAngle, false, mPaint);}@Overridepublic void onSizeChanged(int width, int height) {this.width = width;this.height = height;initInternalCircle();}@Overridepublic void setColor(int color) {this.mColor = color;mPaint.setColor(this.mColor);}@Overridepublic int getColor() {return mColor;}@Overridepublic void setMax(float max) {this.max = max;}public float getMax(){return max;}@Overridepublic void setMin(float min) {this.min = min;}public float getMin(){return min;}@Overridepublic void setValue(float value) {plusAngle = (359.8f * value) / max;}}

绘制中心图片
package lib.vgod.progresscicle.library;import android.graphics.Canvas;import android.graphics.DashPathEffect;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.RectF;/** * @author niuwei * */public class ProgressPainterImp implements ProgressPainter{private float min;private float max;private int mColor;private Paint mPaint;private RectF progressCircle;private float startAngle = 270f;    private float plusAngle = 0;private int width;    private int height;    private int internalStrokeWidth = 48;    private int dashWidth = 5;    private int dashSpace = 8;    private float marginTop = 45;    private float padding;    public ProgressPainterImp(int color, float min, float max){    mColor = color;    this.min = min;    this.max = max;    init();    }        private void init(){    initInternalCirclePainter();    }        private void initInternalCirclePainter() {    mPaint = new Paint();    mPaint.setAntiAlias(true);    mPaint.setColor(mColor);    mPaint.setStrokeWidth(internalStrokeWidth);    mPaint.setStyle(Style.STROKE);    mPaint.setPathEffect(new DashPathEffect(new float[]{dashWidth, dashSpace}, dashSpace));    }        private void initInternalCircle() {    progressCircle = new RectF();        padding = internalStrokeWidth * 1.7f;        progressCircle.set(padding, padding + marginTop, width - padding, height - padding);    }    @Overridepublic void draw(Canvas canvas) {canvas.drawArc(progressCircle, startAngle, plusAngle, false, mPaint);}@Overridepublic void onSizeChanged(int width, int height) {this.width = width;this.height = height;initInternalCircle();}@Overridepublic void setColor(int color) {this.mColor = color;mPaint.setColor(this.mColor);}@Overridepublic int getColor() {return mColor;}@Overridepublic void setMax(float max) {this.max = max;}public float getMax(){return max;}@Overridepublic void setMin(float min) {this.min = min;}public float getMin(){return min;}@Overridepublic void setValue(float value) {plusAngle = (359.8f * value) / max;}}

继承自RelativeLayout的类
package lib.vgod.progresscicle.library;import lib.vgod.progresscicle.R;import android.animation.ValueAnimator;import android.annotation.SuppressLint;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.view.animation.AccelerateDecelerateInterpolator;import android.widget.RelativeLayout;/** * @author niuwei * */@SuppressLint("NewApi") public class DashProgressBar extends RelativeLayout{private final static String TAG = "DashProgressBar";/** * 内圈的颜色 */private int externalCircleColor = Color.GRAY;/** * 外圈的颜色 */private int internalCircleColor = Color.YELLOW;/** * Progress的颜色 */private int progressCircleColor = Color.WHITE;/** * Progress的最大值 */private float progressMax;/** * Progress的最小值 */private float progressMin = 0;/** * Progress的当前值 */private float progressLast = progressMin;/** * 需要显示的图标 */private Bitmap iconBitmap;/** * 动画持续时间 */private int ANIMATION_DURATION = 1000;/** * 动画加速器 */private AccelerateDecelerateInterpolator mInterpolator;/** * 动画 */private ValueAnimator mValueAnimator;/** * 外部执行操作的接口 */private OnValueChangeListener mOnValueChangeListener;/** * 画笔元素 */private ExternalCirclePainter externalCirclePainter;private InternalCirclePainter internalCirclePainter;private BitmapPainter bitmapPainter;private ProgressPainterImp progressPainterImp;private int heightNormalittation = 10;public DashProgressBar(Context context, AttributeSet attrs) {super(context, attrs);init(context, attrs);}public DashProgressBar(Context context, AttributeSet attrs, int defStyle){super(context, attrs, defStyle);init(context, attrs);}/** * 初始化函数 */private void init(Context context, AttributeSet attributeSet){setWillNotDraw(false);initAttributes(attributeSet);initPainter();initData();}/** * 初始化变量 */private void initData(){mInterpolator = new AccelerateDecelerateInterpolator();initAnimate();}/** * 初始化动画 */private void initAnimate(){mValueAnimator = new ValueAnimator();mValueAnimator.setInterpolator(mInterpolator);mValueAnimator.addUpdateListener(new ValueAnimationChangeListener());}/** * 初始化属性 */private void initAttributes(AttributeSet attributeSet){TypedArray ta = getContext().obtainStyledAttributes(attributeSet, R.styleable.DashedCircleProgress);externalCircleColor = ta.getColor(R.styleable.DashedCircleProgress_external_color, externalCircleColor);internalCircleColor = ta.getColor(R.styleable.DashedCircleProgress_base_color, internalCircleColor);progressCircleColor = ta.getColor(R.styleable.DashedCircleProgress_progress_color, progressCircleColor);progressMax = ta.getFloat(R.styleable.DashedCircleProgress_max, progressMax);ANIMATION_DURATION = ta.getInt(R.styleable.DashedCircleProgress_duration, ANIMATION_DURATION);iconBitmap = BitmapFactory.decodeResource(getResources(), ta.getResourceId(R.styleable.DashedCircleProgress_progress_icon, 0));ta.recycle();}/** * 初始化画笔 */private void initPainter(){internalCirclePainter = new InternalCirclePainter(internalCircleColor);externalCirclePainter = new ExternalCirclePainter(externalCircleColor);bitmapPainter = new BitmapPainter(iconBitmap);progressPainterImp = new ProgressPainterImp(progressCircleColor, progressMin, progressMax);}/** * 开始动画 */public void startAnimate(float max){if (mValueAnimator != null) {mValueAnimator.setFloatValues(progressLast, max);mValueAnimator.setDuration(ANIMATION_DURATION);mValueAnimator.start();}}/** * 开始动画 */public void startAnimate(){if (mValueAnimator != null) {mValueAnimator.setFloatValues(progressLast, progressMax);mValueAnimator.setDuration(ANIMATION_DURATION);mValueAnimator.start();}}/** * 重新开始动画 */public void restartAnimate(){progressLast = progressMin;startAnimate(progressMax);}/** * 设置动画执行到什么时候 */public void setValue(int value){if (value <= progressMax && value >= progressMin) {progressLast = progressMin;startAnimate(value);}}/** * 动画监听器,更新内部绘制画面和外部接口回调 * @author niuwei * */private class ValueAnimationChangeListener implements ValueAnimator.AnimatorUpdateListener {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {Float value = (Float)valueAnimator.getAnimatedValue();progressPainterImp.setValue(value);if (mOnValueChangeListener != null) {mOnValueChangeListener.onChange(value);}progressLast = value;}}/** * 接口,当动画改编的过程中UI线程可以进行一些操作  */private interface OnValueChangeListener{void onChange(float change);}@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);Log.d(TAG, "onLayout()");final int count = getChildCount();int maxWidth = getWidth() / 2;int maxHeight = getHeight() / 2;for (int i = 0; i < count; i++) {final View child = getChildAt(i);int mesaureWidth = child.getMeasuredWidth();int measureHeight = child.getMeasuredHeight();ViewGroup.LayoutParams layoutParams = child.getLayoutParams();RelativeLayout.LayoutParams relativeLayoutParams =                    (RelativeLayout.LayoutParams) child.getLayoutParams();            relativeLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT, RelativeLayout.TRUE);            child.setLayoutParams(relativeLayoutParams);if (mesaureWidth > maxWidth) {                layoutParams.width = maxWidth;            }            if (measureHeight > maxHeight) {                layoutParams.height = maxHeight;            }}}@Overrideprotected void onDraw(Canvas canvas){super.onDraw(canvas);Log.d(TAG, "onDraw()");externalCirclePainter.draw(canvas);internalCirclePainter.draw(canvas);bitmapPainter.draw(canvas);progressPainterImp.draw(canvas);invalidate();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec + heightNormalittation);Log.d(TAG, "onMeasure()");}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);Log.d(TAG, "onSizeChanged()");externalCirclePainter.onSizeChanged(w, h);internalCirclePainter.onSizeChanged(w, h);bitmapPainter.onSizeChanged(w, h);progressPainterImp.onSizeChanged(w, h);}public void setmOnValueChangeListener(OnValueChangeListener mOnValueChangeListener) {this.mOnValueChangeListener = mOnValueChangeListener;}}


最后是自定义的属性

<?xml version="1.0" encoding="utf-8"?><resources>   <declare-styleable name="DashedCircleProgress">      <attr name="external_color" format="color" />        <attr name="base_color" format="color" />        <attr name="progress_color" format="color" />        <attr name="max" format="float" />        <attr name="min" format="float" />        <attr name="progress_icon" format="reference" />        <attr name="duration" format="integer" />   </declare-styleable></resources>

大功告成,需要资源可以点击下载 下载

2 0
原创粉丝点击