美文网首页定义控件Android 自定义view开源应用
Android开源音乐播放器之高仿云音乐黑胶唱片

Android开源音乐播放器之高仿云音乐黑胶唱片

作者: 王晨彦 | 来源:发表于2016-06-08 18:01 被阅读4785次

系列文章

前言

上一节我们讨论了一个音乐播放器应该具有的功能,当我们实现了这些功能后,就该考虑如何扩展这些功能了。本节我们要讲的就是专辑封面的美化,看了市面上的播放器,最喜欢云音乐的黑胶唱片专辑封面,下面我们就来模仿一下。

思路分析

云音乐

让我们来分析下这个View,这里有5个地方需要绘制
1.最上面的一条虚线,这个简单。
2.黑胶外侧的半透明边框,这个不需要旋转也比较简单。
3.黑胶
4.专辑封面
为了能使黑胶和封面能完美融合,因此我们需要固定它们的尺寸,这里设置黑胶直径为屏幕的3/4,封面直径为屏幕的一半,即封面直径为黑胶直径的2/3。
5.指针,这个在暂停时会有一个旋转动画,因此注意选择好旋转圆心和半径坐标,为了使指针能够放在黑胶正中,我们需要固定指针的高度为黑胶直径的一半。


分解图

代码实现

声明变量

// 图片起始坐标
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();

确定图片起始坐标与旋转中心坐标

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    initSize();
}

/**
 * 确定图片起始坐标与旋转中心坐标
 */
private void initSize() {
    int discOffsetY = mNeedleBitmap.getHeight() / 2;
    mDiscPoint.x = (getWidth() - mDiscBitmap.getWidth()) / 2;
    mDiscPoint.y = discOffsetY;
    mCoverPoint.x = (getWidth() - mCoverBitmap.getWidth()) / 2;
    mCoverPoint.y = discOffsetY + (mDiscBitmap.getHeight() - mCoverBitmap.getHeight()) / 2;
    mNeedlePoint.x = getWidth() / 2 - mNeedleBitmap.getWidth() / 6;
    mNeedlePoint.y = -mNeedleBitmap.getWidth() / 6;
    mDiscCenterPoint.x = getWidth() / 2;
    mDiscCenterPoint.y = mDiscBitmap.getHeight() / 2 + discOffsetY;
    mCoverCenterPoint.x = mDiscCenterPoint.x;
    mCoverCenterPoint.y = mDiscCenterPoint.y;
    mNeedleCenterPoint.x = mDiscCenterPoint.x;
    mNeedleCenterPoint.y = 0;
}

每次绘制都会进行重复计算,为了优化性能,我们把计算的过程放在onLayout中。
绘制过程

@Override
protected void onDraw(Canvas canvas) {
    // 1.绘制顶部虚线
    mTopLine.setBounds(0, 0, getWidth(), mTopLineHeight);
    mTopLine.draw(canvas);
    // 2.绘制黑胶唱片外侧半透明边框
    mCoverBorder.setBounds(mDiscPoint.x - mCoverBorderWidth, mDiscPoint.y - mCoverBorderWidth,
            mDiscPoint.x + mDiscBitmap.getWidth() + mCoverBorderWidth, mDiscPoint.y +
                    mDiscBitmap.getHeight() + mCoverBorderWidth);
    mCoverBorder.draw(canvas);
    // 3.绘制黑胶
    // 设置旋转中心和旋转角度,setRotate和preTranslate顺序很重要
    mDiscMatrix.setRotate(mDiscRotation, mDiscCenterPoint.x, mDiscCenterPoint.y);
    // 设置图片起始坐标
    mDiscMatrix.preTranslate(mDiscPoint.x, mDiscPoint.y);
    canvas.drawBitmap(mDiscBitmap, 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);
}

到这里我们已经可以实现静态的黑胶唱片专辑封面了,大家根据注释肯定能看懂。
接下来需要添加动画,这里使用匀速的属性动画。
旋转动画

private Runnable mRotationRunnable = new Runnable() {
    @Override
    public void run() {
        if (isPlaying) {
            mDiscRotation += DISC_ROTATION_INCREASE;
            if (mDiscRotation >= 360) {
                mDiscRotation = 0;
            }
            invalidate();
        }
        mHandler.postDelayed(this, TIME_UPDATE);
    }
};

指针动画

mPlayAnimator = ValueAnimator.ofFloat(NEEDLE_ROTATION_PAUSE, NEEDLE_ROTATION_PLAY);
mPlayAnimator.setDuration(300);
mPlayAnimator.addUpdateListener(this);
mPauseAnimator = ValueAnimator.ofFloat(NEEDLE_ROTATION_PLAY, NEEDLE_ROTATION_PAUSE);
mPauseAnimator.setDuration(300);
mPauseAnimator.addUpdateListener(this);

@Override
public void onAnimationUpdate(ValueAnimator animation) {
    mNeedleRotation = (float) animation.getAnimatedValue();
    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);
    mPauseAnimator.start();
}

播放时启动旋转动画,播放指针动画,暂停时暂停动画,播放指针动画。
OK,让我们来看下效果

效果图效果图
基本上和云音乐一样的效果,而且可以自适应屏幕大小,只是看不出来动画效果。
大家可以运行源码或下载波尼音乐查看详细效果。

相关文章

网友评论

  • 晓光_e15c:是如何支持Flac类型的文件的,音频解码用的什么框架,求告知
  • 272abed5ee76:向大神学习~~:smile:
  • e82f13922213:附件在哪,怎么下载
    王晨彦:https://github.com/wangchenyan/PonyMusic
  • 007b89c4d4ca:我想要一个能完整放出音乐的黑胶唱片源码,最好有收藏功能
  • b4c895321d4c:我是初学者, 看你的代码,对我太有帮助了,谢谢
  • ae12:虽然我问的问题你也不会回,但是我真的很想说,图片的起始坐标,真的看了N遍也没看懂
  • f802d51504b6:大神我没有get到黑胶唱片是怎么连续的旋转下去的,能讲讲为什么黑胶唱片能连续旋转下去吗?
    f802d51504b6:@ChayWong 哦明白了谢谢!
    王晨彦:@远音至诚 Handler+Runnable无限循环。
  • f802d51504b6:太厉害了!
  • 空城新月:很漂亮
  • a5123065b997:大神!!!
  • freecats08:不错,这个软件很MD,学习了,大神 :grin:
    e399d859e418:是怎么调用百度音乐的api的
    王晨彦:@freecats08 过奖

本文标题:Android开源音乐播放器之高仿云音乐黑胶唱片

本文链接:https://www.haomeiwen.com/subject/shujdttx.html