自定义View实现网易云音乐留声机效果(代码区)

//绘制旋转了指定角度的唱针
    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);
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值