最近,虽然公司的安卓开发相对还是挺多,依旧在学习自定义View。不怕实现的简单,慢慢做、慢慢理解。
效果图:
1.先实现自定义圆形ImageView:
需要了解上一篇:Android之Canvas绘图中PorterDuffXfermode
首先获取到图片的Bitmap,然后进行裁剪圆形的bitmap,然后在onDraw()进行绘制圆形图片输出。
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
/**
* Created by zachary on 2019/04/08.
* 圆形ImageView
*/
public class MusicView extends AppCompatImageView {
private Paint paint;
public MusicView(Context context) {
this(context,null);
}
public MusicView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MusicView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint = new Paint();
}
@Override
protected void onDraw(Canvas canvas) {
//获取图像资源
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
Bitmap b = getCircleBitmap(bitmap);
//上层
final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());
//下层
final Rect rectDest = new Rect(0,0,getWidth(),getHeight());
paint.reset();
canvas.drawBitmap(b, rectSrc, rectDest, paint);
} else {
super.onDraw(canvas);
}
}
/**
* 获取圆形图片方法
* @param bitmap
* @return Bitmap
*/
private Bitmap getCircleBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffffffff;
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
//设置抗锯齿
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
int x = bitmap.getWidth();
//圆形的大小
canvas.drawCircle(x / 2, x / 2, x / 2, paint);
//PorterDuff.Mode.SRC_IN模式组合效果
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}
2.实现可暂停的旋转效果
因为补间动画(RotateAnimation)只有开始和结束的方法,实现暂停与开始需要记录旋转的角度,而使用属性动画(ObjectAnimator)则可以使用已经封装好的方法,比较适合我们的需求。
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.animation.LinearInterpolator;
/**
* Created by zachary on 2019/04/08.
* 圆形ImageView,旋转操作(属性动画ObjectAnimator)
*/
public class MusicView extends AppCompatImageView {
private ObjectAnimator objectAnimator;
public static final int STATE_PLAYING = 1; //正在播放
public static final int STATE_PAUSE = 2; //暂停
public static final int STATE_STOP = 3; //停止
public int state;
private Paint paint;
public MusicView(Context context) {
this(context,null);
}
public MusicView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MusicView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
paint = new Paint();
init();
}
private void init(){
state = STATE_STOP;
//添加旋转动画,旋转中心默认为控件中点
objectAnimator = ObjectAnimator.ofFloat(this, "rotation", 0f, 360f);
//设置动画时间:3s
objectAnimator.setDuration(3000);
//动画:时间线性渐变
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatCount(ObjectAnimator.INFINITE);
objectAnimator.setRepeatMode(ObjectAnimator.RESTART);
}
/**
* 绘制圆形图片
*/
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
Bitmap b = getCircleBitmap(bitmap);
//上层
final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());
//下层
final Rect rectDest = new Rect(0,0,getWidth(),getHeight());
paint.reset();
canvas.drawBitmap(b, rectSrc, rectDest, paint);
} else {
super.onDraw(canvas);
}
}
/**
* 获取圆形图片方法
* @param bitmap
* @return Bitmap
*/
private Bitmap getCircleBitmap(Bitmap bitmap) {
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
int x = bitmap.getWidth();
canvas.drawCircle(x / 2, x / 2, x / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public void playMusic(){
if(state == STATE_STOP){
objectAnimator.start(); //动画开始
state = STATE_PLAYING;
}else if(state == STATE_PAUSE){
objectAnimator.resume(); //动画重新开始
state = STATE_PLAYING;
}else if(state == STATE_PLAYING){
objectAnimator.pause(); //动画暂停
state = STATE_PAUSE;
}
}
public void stopMusic(){
objectAnimator.end(); //动画结束
state = STATE_STOP;
}
}