Android中,经常会需要用到ProgressDialog这个控件,但是5.0之前,Google官方提供的ProgressDialog大家好像都不怎么看的上眼,通常我们都会自己用图片+动画的形式实现自己闪亮的ProgressDialog,但是更好的方法是我们自己去画一个ProgressDialog,简单好用就行!
下面就来介绍如何画出这样简单的自己的ProgressDialog,也是我们实现Android自定义View的一个开始。
自定义Android控件,我们可以继承View。但是这里我继承的是ImageView,ImageView是View的子类,同继承View类似,但是ImageView为我们提供了许多额外的功能,想想平时使用ImageView那么多的方法属性。
看效果图,需要两种颜色去实现不同的进度条,我们首先将这两种颜色定义在values/attrs.xml(这个文件是自定义控件时定义自己控件属性的一个资源文件)文件下,代码如下:
1
2
3
4
5
6
<resources >
<declare-styleable name ="EUIProgressBar" >
<attr name ="strokecolor" format ="color" />
<attr name ="fillcolor" format ="color" />
</declare-styleable >
</resources >
在后面引用我们自定义ProgressDialog的时候,我们就可以在XML文件中去定义自己想要的颜色,后面会讲到。
接下来,就开始处理我们自己的ProgressDialog部分的代码。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class CustomProgressBar extends ImageView {
public CustomProgressBar (Context context) {
super (context);
}
public CustomProgressBar (Context context, AttributeSet attrs) {
super (context, attrs);
init(context, attrs);
}
public CustomProgressBar (Context context, AttributeSet attrs, int defStyleAttr) {
super (context, attrs, defStyleAttr);
init(context, attrs);
}
}
这就是我们自己的ProgressDialog,这里我们叫它CustomProgressBar,其中有三个构造方法。
在构造方法中,调用了一个自己写的init()方法,主要完成一些初始化的工作,如下:
1
2
3
4
5
6
7
8
9
private void init (final Context context, final AttributeSet attrs) {
final TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.EUIProgressBar);
mStrokeColor = typedArray.getColor(R.styleable.EUIProgressBar_strokecolor, getResources().getColor(R.color.strokecolor));
mFillColor = typedArray.getColor(R.styleable.EUIProgressBar_fillcolor, getResources().getColor(R.color.fillcolor));
typedArray.recycle();
mPaint = new Paint();
mPaint.setAntiAlias(true );
mAccelerateInterpolator = new AccelerateInterpolator();
}
绘制的时候,我们需要知道绘制的圆环的半径,这里我们将半径固定为整个View宽度或者高度的1/2减去一个padding值。在View类中,有一个onSizeChanged(int w, int h, int oldw, int oldh)方法,这里面可以获取当前View最新的宽、高和之前的宽、高,覆写这个方法并在其中初始化我们的圆环的半径以及绘制进度条圆弧所在的矩形。代码如下:
1
2
3
4
5
6
7
8
@Override
protected void onSizeChanged (int w, int h, int oldw, int oldh) {
super .onSizeChanged(w, h, oldw, oldh);
mWidth = w;
mHeight = h;
mRingRadius = mWidth / 2 - CIRCLE_RADIUS;
mRect = new RectF(0 + CIRCLE_RADIUS, 0 + CIRCLE_RADIUS, mWidth - CIRCLE_RADIUS, mHeight - CIRCLE_RADIUS);
}
接下来,就是绘制我们的CustomProgressBar了。覆写onDraw(Canvas canvas)方法并实现自己的绘制代码,如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Override
protected void onDraw (Canvas canvas) {
super .onDraw(canvas);
if (!isDraw || mPaint == null ){
return ;
}
mPaint.setColor(mStrokeColor);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(STROKE_WIDTH);
canvas.drawCircle(mWidth / 2 , mHeight / 2 , mRingRadius, mPaint);
mPaint.setColor(mFillColor);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawArc(mRect, 0 , mAccelerateInterpolator.getInterpolation(mDegress), false , mPaint);
}
现在就已经绘制了自己圆环以及其中的进度条,当然这还是静止的,我们还要让其动起来。很简单,让一个Timer去执行一个TimerTask,并改变圆弧的弧度,代码:
1
2
3
4
5
6
7
8
9
10
11
12
mTask = new TimerTask() {
@Override
public void run () {
if (mDegress == TSZ_FINAL){
exchangeColor();
}
mDegress = mDegress == TSZ_FINAL ? 0 : (float )(mDegress + 0.1 );
postInvalidate();
}
};
mTimer = new Timer();
mTimer.schedule(mTask, 0 , 7 );
差不多就完成了,接下来就是使用这个CustomProgressBar,就像平常在布局文件中使用一个普通控件一样去使用这个CustomProgressBar,不过要在布局文件最顶层加上声明:
xmlns:whilu="http://schemas.android.com/apk/res-auto"
最后添加这个控件,其中我们用到了自定义的属性whilu:strokecolor和whilu:fillcolor,如下所示:
1
2
3
4
5
6
<com.github.wihlu.library.CustomProgressBar
android:id ="@+id/cusprogressbar"
android:layout_width ="80dp"
android:layout_height ="80dp"
whilu:strokecolor ="#ff666666"
whilu:fillcolor ="#ff4387F0" />
最后的效果就是最开始的效果图。
这里简单的示范了自定义一个控件的基本流程,当然还有很多可以扩展的地方。
源码:https://github.com/whilu/EUIProgressBar