仿云音乐黑胶唱片功能

昨天尝试看别人代码,学习了该功能的制作,现在分享出来,方便他人方便自己以后查看。

首先是一堆变量


 private static final long TIME_UPDATE = 50L;//每50毫秒发送一次消息旋转
 private static final float DISC_ROTATION_INCREASE = 0.5f;//每一次旋转的角度,50毫秒0.5度,也就是说36秒一圈
 private static final float NEEDLE_ROTATION_PLAY = 0.0f;//初始播放时指针角度
 private static final float NEEDLE_ROTATION_PAUSE = -25.0f;//播放停止暂停时指针角度

 private Handler mHandler=new Handler();
 private Bitmap mDiscBitamp;//黑胶图片
 private Bitmap mCoverBitmap;//封面图片
 private Bitmap mNeedleBitmap;//指针图片

 //表示一种可以在Canvas上进行绘制抽象的概念,种类很多,最常见的颜色和图片都可以是一个Drawable。
 private Drawable mTopLine;//顶部图像
 private Drawable mCoverBorder;//透明边宽图片

 private int mTopLineHeight;//顶部图像高度
 private int mCoverBorderWidth;//透明边宽厚度

 private Matrix mDiscMatrix = new Matrix();//黑胶样式动作(例如平移旋转)
 private Matrix mCoverMatrix = new Matrix();//封面样式动作(例如平移旋转)
 private Matrix mNeedleMatrix = new Matrix();//指针样式动作(例如平移旋转)

 private ValueAnimator mPlayAnimator;//停止-->播放  动画
 private ValueAnimator mPauseAnimtor;//播放-->停止  动画

 private float mDiscRotation=0.0f;//旋转角度,初始0,最大360
 private float mNeedleRotation=NEEDLE_ROTATION_PLAY;//默认指针时播放时状态角度
 private boolean isPlaying=false;//默认处于停止状态

// 图片起始坐标
private Point mDiscPoint = new Point();
 private Point mCoverPoint = new Point();
 private Point mNeedlePoint = new Point();
 // 旋转中心坐标
 private Point mDiscCenterPoint = new Point();
 private Point mCoverCenterPoint = new Point();
 private Point mNeedleCenterPoint = new Point();


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

在构造函数中初始化参数

mTopLine=getResources().getDrawable(R.drawable.play_page_cover_top_line_shape,null);//初始化drawable
mCoverBorder=getResources().getDrawable(R.drawable.play_page_cover_border_shape,null);//初始化drawable

mDiscBitamp= BitmapFactory.decodeResource(getResources(),R.mipmap.play_page_disc);//初始化黑胶
mDiscBitamp= ImageUtils.resizeImage(mDiscBitamp,(int) (getScreenWidth()*0.75),(int) (getScreenWidth()*0.75));//缩小黑胶图片为屏幕宽度的0.75倍

mNeedleBitmap=BitmapFactory.decodeResource(getResources(),R.mipmap.play_page_needle);//初始化指针
mNeedleBitmap=ImageUtils.resizeImage(mNeedleBitmap,(int) (getScreenWidth()*0.25),(int) (getScreenWidth()*0.375));//缩小图片

mTopLineHeight= (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
        1,getResources().getDisplayMetrics());//顶部横向条,高度为1dp
mCoverBorderWidth= (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
        1,getResources().getDisplayMetrics());//黑胶唱片外侧半透明边框,1dp

//指针动画
/*ValueAnimator的特点就是你不需要明确的指定你要改变的对象和属性,你只需要得到一个动态的值来自己去设置相应对象的属性,
也就是它就是提供属性的变化值,你拿到这个值可以动态的更改对象属性值。总结一句就是监听动画过程,自己实现属性的改变。*/
mPlayAnimator=ValueAnimator.ofFloat(NEEDLE_ROTATION_PAUSE,NEEDLE_ROTATION_PLAY);//指定了值的变化范围
mPlayAnimator.setDuration(300);//变化持续时间
mPlayAnimator.addUpdateListener(this);
mPauseAnimtor=ValueAnimator.ofFloat(NEEDLE_ROTATION_PLAY,NEEDLE_ROTATION_PAUSE);
mPauseAnimtor.setDuration(300);//变化持续时间
mPauseAnimtor.addUpdateListener(this);//开始动画后,我们可以动态的获取变化值

在onLayout方法中,初始化起始坐标以及旋转坐标

int discOffsetY=mNeedleBitmap.getHeight()/2;//指针高度的一半,刚好到黑胶外侧半透明边框(这里假设)
mDiscPoint.x=(getWidth()-mDiscBitamp.getWidth())/2;//黑胶横坐标,1/8的屏幕宽度
mDiscPoint.y=discOffsetY;//黑胶纵坐标,指针的一半

mCoverPoint.x=(getWidth()-mCoverBitmap.getWidth())/2;//封面横坐标,1/4的屏幕宽度
mCoverPoint.y=discOffsetY+(mDiscBitamp.getHeight()-mCoverBitmap.getHeight())/2;//封面纵坐标=指针的一半+(黑胶直径-封面直径)/2
mNeedlePoint.x=getWidth()/2-mNeedleBitmap.getWidth()/6;//指针横坐标
mNeedlePoint.y=-mNeedleBitmap.getHeight()/6;//指针纵坐标

mDiscCenterPoint.x=getWidth()/2;//黑胶,封面的旋转横坐标
mDiscCenterPoint.y=discOffsetY+mDiscBitamp.getWidth()/2;//黑胶,封面的旋转纵坐标

mCoverCenterPoint.x=mDiscCenterPoint.x;
mCoverCenterPoint.y=mDiscCenterPoint.y;

mNeedleCenterPoint.x=mDiscCenterPoint.x;
mNeedleCenterPoint.y=0;

接着在onDraw方法中,绘制

mTopLine.setBounds(0,0,getWidth(),mTopLineHeight);
mTopLine.draw(canvas);

// 2.绘制黑胶唱片外侧半透明边框---   left=黑胶图片的left-边宽厚度,top=黑胶图片的top-边宽厚度
mCoverBorder.setBounds(mDiscPoint.x-mCoverBorderWidth,mDiscPoint.y-mCoverBorderWidth,
        mDiscPoint.x+mDiscBitamp.getWidth()+mCoverBorderWidth,
        mDiscPoint.y+mDiscBitamp.getHeight()+mCoverBorderWidth);
mCoverBorder.draw(canvas);

//3.绘制黑胶, 设置旋转中心和旋转角度,setRotate和preTranslate顺序很重要    set都在pre的后面
mDiscMatrix.setRotate(mDiscRotation,mDiscCenterPoint.x,mDiscCenterPoint.y);//角度+X轴中心+Y轴中心
mDiscMatrix.preTranslate(mDiscPoint.x,mDiscPoint.y);
canvas.drawBitmap(mDiscBitamp,mDiscMatrix,null);//图片,动作样式,画笔

// 4.绘制封面
mCoverMatrix.setRotate(mDiscRotation,mCoverCenterPoint.x,mCoverCenterPoint.y);
mCoverMatrix.preTranslate(mCoverPoint.x,mCoverPoint.y);
canvas.drawBitmap(mCoverBitmap,mCoverMatrix,null);

// 5.绘制指针
mNeedleMatrix.setRotate(mNeedleRotation,mNeedleCenterPoint.x,mNeedleCenterPoint.y);
mNeedleMatrix.preTranslate(mNeedlePoint.x,mNeedlePoint.y);
canvas.drawBitmap(mNeedleBitmap,mNeedleMatrix,null);
//根据播放状态,决定动画动作角度
public void initNeedle(boolean isPlaying){
    mNeedleRotation= isPlaying? NEEDLE_ROTATION_PLAY:NEEDLE_ROTATION_PAUSE;
    invalidate();
}

根据是否播放,初始化指针位置

提供一个方法,没换一个音乐设置一个图片

/**
 * 设置背景图片
 * @param bitmap
 */
public void setCoverBitmap(Bitmap bitmap){
    mCoverBitmap=bitmap;
    //mCoverBitmap=makeRoundCorner(bitmap);
    mDiscRotation=0.0f;//每次换歌,图片旋转角度重置
    invalidate();
}

//播放状态下启动,旋转
public void start(){
    if(isPlaying){//已经在动了,直接返回
        return;
    }
    isPlaying=true;
    mHandler.post(mRotationRunnable);
    mPlayAnimator.start();
}
//停止音乐的时候,移除进程
public void pause(){
    if(!isPlaying){//已经停止了,直接返回
        return;
    }
    isPlaying=false;
    mHandler.removeCallbacks(mRotationRunnable);
    mPauseAnimtor.start();
}
private Runnable mRotationRunnable=new Runnable() {
    @Override
    public void run() {
        if(isPlaying){
            mDiscRotation+=DISC_ROTATION_INCREASE;
            if(mDiscRotation>=360){
                mDiscRotation=0;
            }
            invalidate();
        }
        mHandler.postDelayed(mRotationRunnable,TIME_UPDATE);
    }
};


@Override
public void onAnimationUpdate(ValueAnimator animation) {
    //开始动画后,我们可以动态的获取变化值,     赋值为指针的旋转角度
    mNeedleRotation= (float) animation.getAnimatedValue();
    invalidate();//刷新布局
}
private int getScreenWidth(){
    /*int widthPixels = getResources().getDisplayMetrics().widthPixels;
    return widthPixels;*/
    DisplayMetrics dm=new DisplayMetrics();
    WindowManager wm= (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
    wm.getDefaultDisplay().getMetrics(dm);
    return dm.widthPixels;
}

详情可看http://download.csdn.net/download/a2923790861/10251636链接

更新后功能http://download.csdn.net/download/a2923790861/10255003

猜你喜欢

转载自blog.csdn.net/a2923790861/article/details/79324472
今日推荐