您的位置:首页 > 移动开发 > Android开发

Android 自定义的圆形变化ProgressBar

2015-04-08 13:42 399 查看
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>


大功告成,需要资源可以点击下载 下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: