由于需求需要做一个圆形进度条并且中间填充的是圆形图片并且能有旋转,找了一下没找到合适的,所以自己撸一个。
主要思路是两个控件组合起来。
一个自定义画的圆,另一个自定义一个圆形的imageview。
先看一下主布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="80dp"
android:layout_height="80dp"
>
<com.audioplayer.playmusic.view.customview.CircleProgressBar//圆形进度条
android:id="@+id/cicle_progressBar"
android:layout_width="68dp"
android:layout_height="68dp"
android:layout_centerInParent="true"
/>
<com.audioplayer.playmusic.view.customview.CircleImageView//圆形imageview
android:id="@+id/cicle_image"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
android:src="@drawable/download_bg"/>
</RelativeLayout>
自定义CircleProgressBarAndImageView如下:
/**
* 圆形进度条中间含旋转的图片
*/
public class CircleProgressBarAndImageView extends RelativeLayout {
private Context context;
private CircleProgressBar progressBar;
private CircleImageView imageView;
private View view;
private int imageWidth,imageHeight;
public CircleProgressBarAndImageView(Context context) {
super(context);
}
public CircleProgressBarAndImageView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context=context;
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleProgressbar, 0 , 0);
imageWidth = typeArray.getColor(R.styleable.CircleProgressbar_imageWidth, 58);//获取自定义图片宽度
imageHeight = typeArray.getColor(R.styleable.CircleProgressbar_imageHeight, 58);//获取自定义图片高度
view= LayoutInflater.from(context).inflate(R.layout.audioplayer_progress_image,this,true);
progressBar=view.findViewById(R.id.cicle_progressBar);
imageView=view.findViewById(R.id.cicle_image);
}
/**
* 设置进度
* @param i
*/
public void setProgress(int i){
progressBar.setProgress(i);
}
/**
* 圆形图片开始旋转
*/
ObjectAnimator objectAnimator;
public void imageStartAnimation() {
imageStopAnimation();
if(objectAnimator==null) {
objectAnimator = ObjectAnimator.ofFloat(
imageView, "rotation", 0f, 360f);
objectAnimator.setDuration(7000);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
}
objectAnimator.start();
}
/**
* 圆形图片停止旋转
*/
public void imageStopAnimation() {
if(objectAnimator!=null) {
objectAnimator.end();
}
}
/**
* 给圆形图片控件设置图片
* @param drawable
*/
public void setDrawable(Drawable drawable){
imageView.setImageDrawable(drawable);
}
}
在anim目录下创建image_transtle.xml文件:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<rotate
android:duration="8000"//转动的时间
android:fromDegrees="0.0"//开始角度
android:pivotX="50.0%"//原点坐标的基础上加上的自己宽度的50%
android:pivotY="50.0%"//原点坐标的基础上加上的自己高度的50%
android:repeatCount="infinite"//重复次数
android:repeatMode="restart"//重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果
android:toDegrees="360.0" />//结束角度
</set>
看到的效果就是圆形imageview在圆形进度条中间
接下来我们看一下两个自定义的控件:
CircleProgressBar
/**
* 圆形进度条
*/
public class CircleProgressBar extends View {
// 画圆环的画笔
private Paint ringPaintProgress;
//圆环外面的阴影
private Paint mRingPaintBg;
// 画字体的画笔
// 圆环颜色
private int ringColor,strokeBgColor;
// 半径
private float radius;
// 圆环宽度
private float strokeWidth;
// 总进度
private int totalProgress = 100;
// 当前进度
private int currentProgress=0;
// 透明度
private int alpha = 255;
private int width,height;
private RectF mRectF;
private int imageWidth,imageHeight;
public CircleProgressBar(Context context, AttributeSet attrs) {
super(context, attrs);
initAttrs(context, attrs);
setLayerType(View.LAYER_TYPE_SOFTWARE,null);
initVariable();
}
//获取自定义的一些参数
private void initAttrs(Context context, AttributeSet attrs) {
TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CircleProgressbar, 0 , 0);
radius = typeArray.getDimension(R.styleable.CircleProgressbar_radius, 70);
strokeWidth = typeArray.getDimension(R.styleable.CircleProgressbar_strokeWidth, 6);
ringColor = typeArray.getColor(R.styleable.CircleProgressbar_ringColor, 0xFF4800);
strokeBgColor = typeArray.getColor(R.styleable.CircleProgressbar_strokeBgColor, Color.GRAY);
}
private void initVariable() {
ringPaintProgress = new Paint();
ringPaintProgress.setAntiAlias(true);
ringPaintProgress.setDither(true);
ringPaintProgress.setColor(ringColor);
ringPaintProgress.setStyle(Paint.Style.STROKE);
ringPaintProgress.setStrokeCap(Paint.Cap.ROUND);
ringPaintProgress.setStrokeWidth(strokeWidth);
mRingPaintBg = new Paint();
mRingPaintBg.setAntiAlias(true);
mRingPaintBg.setColor(strokeBgColor);
//mRingPaintBg.setMaskFilter(new BlurMaskFilter(10f, BlurMaskFilter.Blur.SOLID));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
mRingPaintBg.setColor(Color.argb((float) 0.07,0,0,0));
}
mRingPaintBg.setStyle(Paint.Style.STROKE);
mRingPaintBg.setStrokeWidth(4);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//画阴影
mRingPaintBg.setShadowLayer(3f, 0, 0, Color.GRAY);
}
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取当前View的宽高
width=this.getWidth();
height=this.getHeight();
}
@Override
protected void onDraw(Canvas canvas) {
if (currentProgress >= 0) {
mRectF = new RectF(getWidth() / 2 - radius, getHeight() / 2 - radius, getWidth() / 2 + radius, getHeight() / 2 + radius);
canvas.drawArc(mRectF, -90, 360, false, mRingPaintBg);//画圆环背景包含阴影
//画进度条
canvas.drawArc(mRectF, -90, ((float) currentProgress / totalProgress) * 360, false, ringPaintProgress);//画进度条
}
}
/**
* 设置进度
* @param progress
*/
public void setProgress(int progress) {
currentProgress = progress;
postInvalidate();//设置完进度重新刷新绘制
}
}
CircleImageView
/**
* 圆形ImageView图片
*/
public class CircleImageView extends AppCompatImageView {
private float width;//控件的宽度
private float height;//控件的呃高度
private float radius;//圆的半径
private Paint paint;//画笔
private Matrix matrix;//矩阵
public CircleImageView(Context context) {
this(context, null);
}
public CircleImageView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
paint.setAntiAlias(true); //设置抗锯齿
matrix = new Matrix(); //初始化缩放矩阵
}
/**
* 测量控件的宽高,并获取其内切圆的半径
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getMeasuredWidth();
height = getMeasuredHeight();
radius = Math.min(width, height) / 2;
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
super.onDraw(canvas);
return;
}
if (drawable instanceof BitmapDrawable) {
paint.setShader(initBitmapShader((BitmapDrawable) drawable));//将着色器设置给画笔
canvas.drawCircle(width / 2, height / 2, radius, paint);//使用画笔在画布上画圆
return;
}
super.onDraw(canvas);
}
/**
* 获取ImageView中资源图片的Bitmap,利用Bitmap初始化图片着色器,通过缩放矩阵将原资源图片缩放到铺满整个绘制区域,避免边界填充
*/
private BitmapShader initBitmapShader(BitmapDrawable drawable) {
Bitmap bitmap = drawable.getBitmap();
BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
float scale = Math.max(width / bitmap.getWidth(), height / bitmap.getHeight());
matrix.setScale(scale, scale);//将图片宽高等比例缩放,避免拉伸
bitmapShader.setLocalMatrix(matrix);
return bitmapShader;
}
在activity使用此控件:
CircleProgressBarAndImageView float_progressbar= findView(R.id.float_progressbar);
//设置进度
float_progressbar.setProgress(int progress);
//圆形图片开始旋转
float_progressbar.imageStartAnimation();
//圆形图片结束旋转
float_progressbar.imageStopAnimation();