仿CD状图片旋转,暂停及恢复

CD状图片

我在写音乐播放器的时候,在播放界面需要CD状图片,这里我们就要自定义控件了,因为系统中没有自带的这种控件。(关于自定义控件可以看我这篇博客:传送门
因为CD图片肯定是要载入图片的,所以我们直接继承ImageView就好了。然后在OnMeasure方法中进行大小的测量,OnDraw方法中进行样式的绘制。

package com.gin.xjh.shin_music.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.util.AttributeSet;

public class cd_ImageView extends android.support.v7.widget.AppCompatImageView {

    private Paint mPaint; //画笔

    private int mRadius; //圆形图片的半径

    private float mScale; //图片的缩放比例

    public cd_ImageView(Context context) {
        super(context);
    }

    public cd_ImageView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public cd_ImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //因为是圆形图片,所以应该让宽高保持一致
        int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
        mRadius = size / 2;

        setMeasuredDimension(size, size);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        mPaint = new Paint();
        Bitmap bitmap = drawableToBitmap(getDrawable());

        //初始化BitmapShader,传入bitmap对象
        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        //计算缩放比例
        mScale = (mRadius * 0.7f * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());

        Matrix matrix = new Matrix();
        matrix.setScale(mScale, mScale);
        bitmapShader.setLocalMatrix(matrix);
        mPaint.setAntiAlias(true);

        mPaint.setColor(Color.BLACK);
        canvas.drawCircle(mRadius, mRadius, mRadius, mPaint);

        //画圆形,指定好中心点坐标、半径、画笔
        mPaint.setShader(bitmapShader);
        canvas.translate(mRadius * 0.30f, mRadius * 0.30f);
        //canvas.rotate(degree, mRadius * 0.7f, mRadius * 0.7f);
        canvas.drawCircle(mRadius * 0.7f, mRadius * 0.7f, mRadius * 0.7f, mPaint);

    }

    //写一个drawble转BitMap的方法
    private Bitmap drawableToBitmap(Drawable drawable) {
        if (drawable instanceof BitmapDrawable) {
            BitmapDrawable bd = (BitmapDrawable) drawable;
            return bd.getBitmap();
        }
        int w = drawable.getIntrinsicWidth();
        int h = drawable.getIntrinsicHeight();
        Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        drawable.setBounds(0, 0, w, h);
        drawable.draw(canvas);
        return bitmap;
    }

}

主要将下面这几条代码注释一下,这些代码是主要的测量及绘制:
OnMeasure中:

int size = Math.min(getMeasuredWidth(), getMeasuredHeight());
mRadius = size / 2;
setMeasuredDimension(size, size);

因为传入的图片可能宽高是不同的,所以我们画圆形图片不要留白,所以取最小值,然后圆形图片的半径应该就是这个的一半

OnDraw中:

mScale = (mRadius * 0.7f * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth());
Matrix matrix = new Matrix();
matrix.setScale(mScale, mScale);

计算缩放的比例,因为CD样式,所以我们在结合控件大小还需要缩小到70%,所以需要乘上0.7

canvas.translate(mRadius * 0.30f, mRadius * 0.30f);
canvas.drawCircle(mRadius * 0.7f, mRadius * 0.7f, mRadius * 0.7f, mPaint);

因为先画了一个原本大小的黑色圆形。然后我们要画中间的图片了,但是不能直接画,因为现在图片的坐标系是需要变化的,记住translate方法并不是移动画布而是移动坐标系,然后把Bitmap画上去就好了。


旋转,暂停及恢复

方法一:通过线程进行计时然后对Canvas进行旋转

因为我们需要不断的刷新界面,所以不推荐使用。

private volatile float degree = 0;//角度
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
    @Override
    public void run() {
        synchronized (cd_ImageView.class) {
            degree += 2f;
            if (degree > 360f) {
                degree -= 360f;
            }
            invalidate();//重新绘制View
            handler.postDelayed(this, 16l);
        }
    }
};

不断的计算角度,通过handler的计时重新调用来不断的重新绘制View。
onDraw中绘制CD图片之前添加:

canvas.rotate(degree, mRadius * 0.7f, mRadius * 0.7f);

开始,暂停,恢复代码

public void start() {
    handler.post(runnable);
}
public void pause() {
    handler.removeCallbacks(runnable);
}
@Override
protected void onDetachedFromWindow() {
    super.onDetachedFromWindow();
    handler.removeCallbacksAndMessages(null);
}
通过动画实现

我们设定好动画的属性:

//设定动画作用于的控件,以及什么动画,旋转的开始角度和结束角度
objAnim = ObjectAnimator.ofFloat(mAlbum, "rotation", 0.0f, 360.0f);
//设定动画的旋转周期
objAnim.setDuration(20000);
//设置动画的插值器,这个为匀速旋转
objAnim.setInterpolator(new LinearInterpolator());
//设置动画为无限重复
objAnim.setRepeatCount(-1);
//设置动画重复模式
objAnim.setRepeatMode(ObjectAnimator.RESTART);

动画开始

objAnim.start();

动画暂停

objAnim.pause();

动画恢复

objAnim.resume();

动画停止

objAnim.end();

对控件清除动画

mAlbum.clearAnimation();

效果如下:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值