Android 自定义的圆形变化ProgressBar
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() { @Override public void onClick(View arg0) { dashProgressBar.startAnimate(); } }); restartBtn.setOnClickListener(new View.OnClickListener() { @Override public 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); } @Override public void draw(Canvas canvas) { canvas.drawArc(externalCircle, startAngle, finishAngle, false, externalPainter); } @Override public void onSizeChanged(int width, int height) { this.width = width; this.height = height; initExternalCircle(); } @Override public void setColor(int color) { this.color = color; } @Override public 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); } @Override public void draw(Canvas canvas) { canvas.drawArc(internalCircle, startAngle, finishAngle, false, internalCirclePaint); } @Override public void onSizeChanged(int width, int height) { this.width = width; this.height = height; initInternalCircle(); } @Override public void setColor(int color) { this.color = color; internalCirclePaint.setColor(this.color); } @Override public 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); } @Override public void draw(Canvas canvas) { canvas.drawArc(progressCircle, startAngle, plusAngle, false , mPaint); } @Override public void onSizeChanged(int width, int height) { this.width = width; this.height = height; initInternalCircle(); } @Override public void setColor(int color) { this.mColor = color; mPaint.setColor(this.mColor); } @Override public int getColor() { return mColor; } @Override public void setMax(float max) { this.max = max; } public float getMax(){ return max; } @Override public void setMin(float min) { this.min = min; } public float getMin(){ return min; } @Override public 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); } @Override public void draw(Canvas canvas) { canvas.drawArc(progressCircle, startAngle, plusAngle, false , mPaint); } @Override public void onSizeChanged(int width, int height) { this.width = width; this.height = height; initInternalCircle(); } @Override public void setColor(int color) { this.mColor = color; mPaint.setColor(this.mColor); } @Override public int getColor() { return mColor; } @Override public void setMax(float max) { this.max = max; } public float getMax(){ return max; } @Override public void setMin(float min) { this.min = min; } public float getMin(){ return min; } @Override public 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 { @Override public 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); } @Override protected 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; } } } @Override protected void onDraw(Canvas canvas){ super.onDraw(canvas); Log.d(TAG, "onDraw()"); externalCirclePainter.draw(canvas); internalCirclePainter.draw(canvas); bitmapPainter.draw(canvas); progressPainterImp.draw(canvas); invalidate(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec + heightNormalittation); Log.d(TAG, "onMeasure()"); } @Override protected 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>
大功告成,需要资源可以点击下载 下载
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。