//绘制旋转了指定角度的唱针
private void drawNeedle(Canvas canvas,int degree){
//移动坐标到水平中点
canvas.save();
canvas.translate(halfMeassuredWidth,0);
//绘制唱针手臂
needPaint.setStrokeWidth(20);
needPaint.setColor(Color.parseColor("#C0C0C0"));
//绘制第一段臂
canvas.rotate(degree);
canvas.drawLine(0,0,0,longArmLength,needPaint);
//绘制第二段臂
canvas.translate(0,longArmLength);
canvas.rotate(-30);
canvas.drawLine(0,0,0,shortArmLength,needPaint);
//绘制唱针头
//绘制第一段唱针头
canvas.translate(0,longHeadLength);
needPaint.setStrokeWidth(40);
canvas.drawLine(0,0,0,longHeadLength,needPaint);
//绘制第二段唱针头
canvas.translate(0,longHeadLength);
needPaint.setStrokeWidth(60);
canvas.drawLine(0,0,0,shortHeadLength,needPaint);
canvas.restore();
//两个重叠的圆形
canvas.save();
canvas.translate(halfMeassuredWidth,0);
needPaint.setStyle(Paint.Style.FILL);
needPaint.setColor(Color.parseColor("#C0C0C0"));
canvas.drawCircle(0,0,bigCircleRadius,needPaint);
needPaint.setColor(Color.parseColor("#8A8A8A"));
canvas.drawCircle(0,0,samllCircleRadius,needPaint);
canvas.restore();
}
public class GramophoneView extends View{
private int halfMeassuredWidth;// 绘制唱片相关变量
private static final int DEFAULT_PICTURE_RADIUS = 400;// 中间图片默认半径
private static final float DEFAULT_DISK_ROTATE_SPEED = 0.3f; // 唱片旋转默认速度,其实是通过每次旋转叠加的角度来控制速度
private int pictureRadius; //中间图片的半径
private int ringWidth; //黑色圆环宽度
private float diskRotateSpeed; //唱片旋转速度
private Paint discPaint; //唱片画笔
private Path clipPath; //裁剪图片的路径
private Bitmap bitmap; //图片
private Rect srcRect; //图片被裁剪范围
private Rect dstRect; //图片被绘制范围
private static final int PLAY_DEGREE = -15;//播放状态唱针的旋转角度
private static final int PAUSE_DEGREE = -45;//暂停状态唱针的旋转角度
private int samllCircleRadius = 20;//唱针顶部小圆半径
private int bigCircleRadius;//唱针顶部大圆半径
private int longArmLength; //唱针手臂,较长那段的长度
private int shortArmLength; //唱针手臂,较短那段的长度
private int longHeadLength; //唱针的头,较长那段的长度
private int shortHeadLength; //唱针的头,较短那段的长度
private Paint needPaint; //唱针画笔
private boolean isPlaying; //是否处于播放状态
private int needleDegreeCounter; //唱针旋转角度计数器
private float diskDegreeCounter; //唱片旋转角度计数器
public GramophoneView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.GramophoneView);
pictureRadius = (int) typedArray.getDimension(R.styleable.GramophoneView_picture_radius,DEFAULT_PICTURE_RADIUS);
diskRotateSpeed = typedArray.getFloat(R.styleable.GramophoneView_disk_rotate_speed,DEFAULT_DISK_ROTATE_SPEED);
Drawable drawable = typedArray.getDrawable(R.styleable.GramophoneView_src);
if (drawable==null){
bitmap = BitmapFactory.decodeResource(getResources(),R.mipmap.gramophone_view_default_picture);
}else {
bitmap = ((BitmapDrawable)drawable).getBitmap();
}
typedArray.recycle();
//初始化唱片变量
ringWidth = pictureRadius>>1;
discPaint = new Paint();
discPaint.setColor(Color.BLACK);
discPaint.setStyle(Paint.Style.STROKE);
discPaint.setStrokeWidth(ringWidth);
srcRect = new Rect();
dstRect = new Rect();
setBitmapRect(srcRect,dstRect);
clipPath = new Path();
clipPath.addCircle(0,0,pictureRadius,Path.Direction.CW);
diskDegreeCounter = 0;
//初始化唱针变量
bigCircleRadius = samllCircleRadius<<1;
shortHeadLength = (pictureRadius + ringWidth)/15;
longHeadLength = shortHeadLength<<1;
shortArmLength = longHeadLength<<1;
longArmLength = shortArmLength<<1;
needPaint = new Paint();
needleDegreeCounter = PAUSE_DEGREE;
}
}
//绘制旋转了指定角度的唱片(类似唱针,唱片里面的图片是会旋转不同角度的)
private void drawDisk(Canvas canvas,float degree){
//移动坐标系到唱针下方合适位置,然后旋转指定角度
//save():用来保存Canvas的状态,save()方法之后的代码,能够调用Canvas的平移、放缩、旋转、裁剪等操作!
canvas.save();
canvas.translate(halfMeassuredWidth,pictureRadius+ringWidth+longArmLength);
canvas.rotate(degree);
//绘制圆环
canvas.drawCircle(0,0,pictureRadius+ringWidth/2,discPaint);
//绘制图片
canvas.clipPath(clipPath);
canvas.drawBitmap(bitmap,srcRect,dstRect,discPaint);
canvas.restore();
//.restore():用来恢复Canvas之前保存的状态,防止save()方法代码之后对Canvas运行的操作。继续对兴许的绘制会产生影响。通过该方法能够避免连带的影响!
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
halfMeassuredWidth = getMeasuredWidth()>>1;
drawDisk(canvas);//绘制唱片
drawNeedle(canvas);//绘制唱针
// 如果唱针当前角度大于暂停状态下的角度(注意了由于是负数所以是大于),
// 继续重绘
if (needleDegreeCounter > PAUSE_DEGREE){
invalidate();
}
}
//绘制唱片(胶片)
private void drawDisk(Canvas canvas) {
// 这里的diskRotateSpeed变量就是唱片每次变化角度,就是旋转速度的意思
diskDegreeCounter = diskDegreeCounter%360 + diskRotateSpeed;
drawDisk(canvas,diskDegreeCounter);
}
private void drawNeedle(Canvas canvas) {
//根据播放/暂停状态控制唱针角度的加/减变化
if(isPlaying){
if (needleDegreeCounter < PLAY_DEGREE){
needleDegreeCounter += 3;
Log.e("zhangyubin",needleDegreeCounter+"");
}
}else {
if (needleDegreeCounter >PAUSE_DEGREE){
needleDegreeCounter -=3;
Log.e("zhangyubin",needleDegreeCounter+"");
}
}
drawNeedle(canvas,needleDegreeCounter);
}