首先我们先来看看最终的效果
现在我们来一步一步实现这个效果
- 首先我们先自定义VIew,把唱片背景图画上去,代码很简单
- 定义一个Bitmap变量,保存唱片图片,在初始化方法中获取唱片图片
//获取唱片图片Bitmap
discBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.play_page_disc);
//转换图片大小
discBitmap = ImageUtils.resizeImage(discBitmap, (int) (Util.getScreenWidth(getContext()) * 0.75), (int) (Util.getScreenWidth(getContext()) * 0.75));
- 在View的onDraw方法中绘制图片
//绘制唱片图片
canvas.drawBitmap(discBitmap,0,0,null);
- 现在运行我们来看看效果
- 图片没有居中,我们把它居中起来
定义图片的Matrix和Point
private Matrix discMatrix = new Matrix();//唱片图片的Matrix对象,此处使用Matrix,方便后面做旋转功能
private Point discPoint = new Point();//唱片图片的位置
定义初始化位置的方法,在自定义View的onLayout()中调用
/**
* 初始化位置
*/
private void initSize() {
//唱片图片的位置
discPoint.x = (getWidth() - discBitmap.getWidth()) / 2;
}
修改我们的绘制方法
discMatrix.preTranslate(discPoint.x, 0f); //图片居中
//绘制唱片图片
canvas.drawBitmap(discBitmap, discMatrix, null);
- 现在我们再来看看运行效果,可以看到图片已经居中啦
- 下一步我们让图片旋转起来
Matrix的setRotate(float degrees, float px, float py)的方法可以旋转图片,参数分别为旋转角度,旋转中心点X轴值和旋转中心点Y轴的值
我们可以定义一个变量保存旋转的角度,使用一个定时器不断的改变这个值,然后重绘页面,就可以使图片不停的旋转起来啦
private float discRotation = 0.0f;//唱片图片和中心歌曲海报旋转的角度,
private static final float DISC_ROTATION_INCREASE = 0.5f;//每次旋转的角度
在画图片的时候,把设置图片的旋转中心和旋转角度,注意此处要放在图片居中的前面,且要使用setRotate()方法
//图片旋转
discMatrix.setRotate(discRotation, discCenterPoint.x, discCenterPoint.y);
/**
* 创建一个定时任务,定时改变图片的选择角度
*/
private Runnable rotationRunnable = new Runnable() {
@Override
public void run() {
discRotation += DISC_ROTATION_INCREASE;
if (discRotation >= 360) {
discRotation = 0;
}
//通知页面重绘
invalidate();
myHandler.postDelayed(this, TIME_UPDATE);
}
};
/**
* 开始播放
*/
public void startPlay() {
if (isPlaying) {
return;
}
isPlaying = true;
//启动定时器,执行旋转动画
myHandler.post(rotationRunnable);
}
- 由于只有一个唱片图片,旋转起来不能明细看到效果,我们现在来添加歌曲封面图片
首先定义封面图片和位置对象
private Bitmap coverBitmap;//歌曲封面图片
private Matrix coverMatrix = new Matrix();//封面图片的Matrix
private Point coverPoint = new Point();//封面图片的位置
初始化图片
//获取封面图片Bitmap
coverBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.cover);
//转换图片大小
coverBitmap=ImageUtils.resizeImage(coverBitmap,Util.getScreenWidth(getContext()) / 2,Util.getScreenWidth(getContext()) / 2);
//将图片剪裁为圆形
coverBitmap = ImageUtils.createCircleImage(coverBitmap);
设置位置
//封面图片的位置
coverPoint.x = (getWidth() - coverBitmap.getWidth()) / 2;
coverPoint.y = (discBitmap.getHeight() - coverBitmap.getHeight()) / 2;
绘制图片,此处旋转图片的参数可以直接使用唱片图片的
//图片旋转
coverMatrix.setRotate(discRotation, discCenterPoint.x, discCenterPoint.y);
//图片位置
coverMatrix.preTranslate(coverPoint.x, coverPoint.y);
//绘制封面图片
canvas.drawBitmap(coverBitmap, coverMatrix, null);
-
现在我们再来看看效果
-
好了,到现在我们已经实现主要功能啦,下一步我们来添加右上角的指针图片
和原来一样,添加存储图片位置等数据的变量
private Bitmap needleBitmap;//指针图片
private Matrix needleMatrix = new Matrix();//指针图片的Matrix
private Point needlePoint = new Point();//指针图片的位置
初始化图片
//获取指针图片Bitmap
needleBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.play_page_needle);
//转换图片大小
needleBitmap = ImageUtils.resizeImage(needleBitmap, (int) (Util.getScreenWidth(getContext()) * 0.25),
(int) (Util.getScreenWidth(getContext()) * 0.375));
设置位置,
//指针图片的位置
needlePoint.x = (getWidth() - needleBitmap.getWidth()) / 2 +100;
**此处注意,指针图片在唱片图和封面图片的上面,所以唱片图片和封面图片的高度需要调整,需要加上 指针图片的高度 / 2 **
int discOffsetY = needleBitmap.getHeight() / 2 + 20;
最后我们把图片画上去
//指针图片
needleMatrix.setTranslate(needlePoint.x, needlePoint.y);
canvas.drawBitmap(needleBitmap, needleMatrix, null);
- 现在我们来看看效果
- 看看,是不是和网易云的一样啦
- 别急,我们还有最后一步,那就是指针在播放时和暂停时的位置是不一样的,我们注意到,指针在播放和暂停时,只是旋转了一下,我们来尝试实现一下
我们先来修改一下指针默认的位置,默认是暂停的嘛
private static final float NEEDLE_ROTATION_PLAY = 0.0f;//播放时指针的旋转角度
private static final float NEEDLE_ROTATION_PAUSE = -25.0f;//暂停时指针的旋转角度
我们定义一下指针旋转的中心点和定义一个属性动画
private Point needleCenterPoint = new Point();//指针旋转中心角度
private ValueAnimator needleAnimator;//播放时,指针旋转的属性动画
然后初始化属性动画
//初始化指针旋转动画
needleAnimator = ValueAnimator.ofFloat(NEEDLE_ROTATION_PAUSE, NEEDLE_ROTATION_PLAY);
needleAnimator.setDuration(500);
needleAnimator.addUpdateListener(animatorUpdateListener);
/**
* 属性动画变化监听器
*/
ValueAnimator.AnimatorUpdateListener animatorUpdateListener=new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
if(isPlaying){//判断是否正在播放
needleRotation = (float) valueAnimator.getAnimatedValue();
}else{
needleRotation = - ((float) valueAnimator.getAnimatedValue() + 25);
}
invalidate();
}
};
最后在播放和暂停执行属性动画
needleAnimator.start();
- 好了,最后我们再看效果
看,是不是和开始的效果一样啦~
代码和资源文件已经上传到Github,需要可以自取哦
Github:PlayView
第一次写博客,有些的不好的地方请大家见谅啊,欢迎大家留言交流~~~
PS:仿网易云播放页面的博客有很多,如有雷同,不慎巧合,哈哈T_T