Android開源音樂播放器之高仿雲音樂黑膠唱片

chay發表於2019-01-10

系列文章

前言

上一節我們討論了一個音樂播放器應該具有的功能,當我們實現了這些功能後,就該考慮如何擴充套件這些功能了。本節我們要講的就是專輯封面的美化,看了市面上的播放器,最喜歡雲音樂的黑膠唱片專輯封面,下面我們就來模仿一下。

思路分析

雲音樂
讓我們來分析下這個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,讓我們來看下效果

效果圖

基本上和雲音樂一樣的效果,而且可以自適應螢幕大小,只是看不出來動畫效果。 大家可以執行原始碼或下載波尼音樂檢視詳細效果。

遷移自我的簡書 2016.06.08

相關文章