昨天尝试看别人代码,学习了该功能的制作,现在分享出来,方便他人方便自己以后查看。
首先是一堆变量
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