自定义圆形进度条
其实圆形进度条总体上来说是比较简单的,简单的步骤如下:
1、继承一个View或者Drawable,本教程选择Drawable;
2、重写public void draw(Canvas canvas){...}函数,在该函数中画圆环,其中有一个参数progress用来指定画圆弧的角度。
3、在进行下载操作的controller中实时变更progress,并在setProgress方法中重绘。
源码:ZyCircularProgressDrawable类
package com.example.ustc_zy.myapplication;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
/**
* Created by ustc-zy on 15-10-28.
*/
public class ZyCircularProgressDrawable extends Drawable {
public boolean isRunning = false;
public static final String PROGRESS_PROPERTY="progress";
public static final String RING_COLOR="ringColor";
private float progress = 0;
private int ringWidth;
private int ringColor;
private int ringBackgroundColor;
private Paint paint;
protected final RectF arcElements;
private int max = 100;
ZyCircularProgressDrawable(int ringWidth, int ringColor, int ringBackgroundColor){
this.ringWidth = ringWidth;
this.paint = new Paint();
paint.setAntiAlias(true);
this.ringColor = ringColor;
this.ringBackgroundColor = ringBackgroundColor;
arcElements = new RectF();
}
@Override
public void draw(Canvas canvas) {
final Rect bounds = getBounds();
int size = Math.min(bounds.height(), bounds.width());
float outerRadius = (size / 2) - (ringWidth / 2);
float offsetX = (bounds.width() - outerRadius * 2) / 2;
float offsetY = (bounds.height() - outerRadius * 2 ) / 2;
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(1);
paint.setColor(ringBackgroundColor);
canvas.drawCircle(bounds.centerX(), bounds.centerY(), outerRadius, paint);
int halfRingWidth = ringWidth / 2;
float arcX0 = offsetX + halfRingWidth;
float arcY0 = offsetY + halfRingWidth;
float arcX = offsetX + outerRadius * 2 - halfRingWidth;
float arcY = offsetY + outerRadius * 2 - halfRingWidth;
paint.setColor(ringColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(ringWidth);
paint.setStrokeCap(Paint.Cap.ROUND);
arcElements.set(arcX0, arcY0, arcX, arcY);
// if(indeterminate) {
// canvas.drawArc(arcElements, progress, 90, false, paint);
// }else{
// canvas.drawArc(arcElements, 89, progress, false, paint);
// }
canvas.drawArc(arcElements,89, progress ,false, paint);
}
@Override
public void setAlpha(int alpha) {
paint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter colorFilter) {
paint.setColorFilter(colorFilter);
}
@Override
public int getOpacity() {
return 1-paint.getAlpha();
}
public void setProgress(float progress) {
// if(indeterminate) {
// this.progress = progress;
// }else{
// this.progress = PROGRESS_FACTOR * progress;
// }
this.progress = progress;
invalidateSelf();
}
public void setRingColor(int ringColor){
this.ringColor = ringColor;
invalidateSelf();
}
private boolean indeterminate = false;
public boolean isIndeterminate(){return indeterminate;}
public void setIndeterminate(boolean indeterminate){this.indeterminate = indeterminate;}
}
package com.example.ustc_zy.myapplication;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
ImageView imageView;
Button button;
ZyCircularProgressDrawable drawable;
Animator currentAnimator;
View.OnClickListener listener = new View.OnClickListener() {
@Override
public void onClick(View v) {
if(currentAnimator != null){
currentAnimator.cancel();
}
switch (v.getId()){
case R.id.imageView:
currentAnimator = prepareRingAnimation();
break;
}
currentAnimator.start();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
@Override
protected void onResume(){
super.onResume();
imageView = (ImageView)findViewById(R.id.imageView);
button = (Button)findViewById(R.id.button);
drawable = new ZyCircularProgressDrawable(getResources().getDimensionPixelSize(R.dimen.ringWidth)
,getResources().getColor(android.R.color.holo_blue_bright)
,getResources().getColor(android.R.color.darker_gray));
imageView.setImageDrawable(drawable);
imageView.setOnClickListener(listener);
button.setOnClickListener(this);
}
public void downloadFile(){
Thread downloadThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while(i < 360){
i++;
try {
Thread.sleep(500);
Message msg = new Message();
msg.arg1 = i;
handler.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
downloadThread.start();
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg){
int progress = msg.arg1;
drawable.setProgress((float) progress);
}
};
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
private Animator prepareRingAnimation() {
AnimatorSet animator = new AnimatorSet();
ObjectAnimator progressAnimation = ObjectAnimator.ofFloat(drawable
, ZyCircularProgressDrawable.PROGRESS_PROPERTY, 0f, 1f);
progressAnimation.setDuration(3600);
progressAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
ObjectAnimator coloeAnimator = ObjectAnimator.ofInt(drawable
, ZyCircularProgressDrawable.RING_COLOR
,getResources().getColor(android.R.color.holo_green_dark),
getResources().getColor(android.R.color.holo_blue_bright));
coloeAnimator.setEvaluator(new ArgbEvaluator());
coloeAnimator.setDuration(3600);
animator.playTogether(progressAnimation, coloeAnimator);
return animator;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button:
downloadFile();
break;
}
}
}