系列文章
- Android開(kāi)源在線音樂(lè)播放器——波尼音樂(lè)
- Android開(kāi)源音樂(lè)播放器之播放器基本功能
- Android開(kāi)源音樂(lè)播放器之高仿云音樂(lè)黑膠唱片
- Android開(kāi)源音樂(lè)播放器之自動(dòng)滾動(dòng)歌詞
- Android開(kāi)源音樂(lè)播放器之在線音樂(lè)列表自動(dòng)加載更多
前言
上一節(jié)我們討論了一個(gè)音樂(lè)播放器應(yīng)該具有的功能,當(dāng)我們實(shí)現(xiàn)了這些功能后韩脑,就該考慮如何擴(kuò)展這些功能了氢妈。本節(jié)我們要講的就是專輯封面的美化,看了市面上的播放器段多,最喜歡云音樂(lè)的黑膠唱片專輯封面首量,下面我們就來(lái)模仿一下。
思路分析
讓我們來(lái)分析下這個(gè)View进苍,這里有5個(gè)地方需要繪制
1.最上面的一條虛線加缘,這個(gè)簡(jiǎn)單。
2.黑膠外側(cè)的半透明邊框觉啊,這個(gè)不需要旋轉(zhuǎn)也比較簡(jiǎn)單拣宏。
3.黑膠
4.專輯封面
為了能使黑膠和封面能完美融合,因此我們需要固定它們的尺寸杠人,這里設(shè)置黑膠直徑為屏幕的3/4勋乾,封面直徑為屏幕的一半,即封面直徑為黑膠直徑的2/3嗡善。
5.指針辑莫,這個(gè)在暫停時(shí)會(huì)有一個(gè)旋轉(zhuǎn)動(dòng)畫(huà),因此注意選擇好旋轉(zhuǎn)圓心和半徑坐標(biāo)罩引,為了使指針能夠放在黑膠正中各吨,我們需要固定指針的高度為黑膠直徑的一半。
代碼實(shí)現(xiàn)
聲明變量
// 圖片起始坐標(biāo)
private Point mDiscPoint = new Point();
private Point mCoverPoint = new Point();
private Point mNeedlePoint = new Point();
// 旋轉(zhuǎn)中心坐標(biāo)
private Point mDiscCenterPoint = new Point();
private Point mCoverCenterPoint = new Point();
private Point mNeedleCenterPoint = new Point();
確定圖片起始坐標(biāo)與旋轉(zhuǎn)中心坐標(biāo)
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
initSize();
}
/**
* 確定圖片起始坐標(biāo)與旋轉(zhuǎn)中心坐標(biāo)
*/
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;
}
每次繪制都會(huì)進(jìn)行重復(fù)計(jì)算袁铐,為了優(yōu)化性能揭蜒,我們把計(jì)算的過(guò)程放在onLayout
中。
繪制過(guò)程
@Override
protected void onDraw(Canvas canvas) {
// 1.繪制頂部虛線
mTopLine.setBounds(0, 0, getWidth(), mTopLineHeight);
mTopLine.draw(canvas);
// 2.繪制黑膠唱片外側(cè)半透明邊框
mCoverBorder.setBounds(mDiscPoint.x - mCoverBorderWidth, mDiscPoint.y - mCoverBorderWidth,
mDiscPoint.x + mDiscBitmap.getWidth() + mCoverBorderWidth, mDiscPoint.y +
mDiscBitmap.getHeight() + mCoverBorderWidth);
mCoverBorder.draw(canvas);
// 3.繪制黑膠
// 設(shè)置旋轉(zhuǎn)中心和旋轉(zhuǎn)角度昭躺,setRotate和preTranslate順序很重要
mDiscMatrix.setRotate(mDiscRotation, mDiscCenterPoint.x, mDiscCenterPoint.y);
// 設(shè)置圖片起始坐標(biāo)
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);
}
到這里我們已經(jīng)可以實(shí)現(xiàn)靜態(tài)的黑膠唱片專輯封面了忌锯,大家根據(jù)注釋肯定能看懂。
接下來(lái)需要添加動(dòng)畫(huà)领炫,這里使用勻速的屬性動(dòng)畫(huà)偶垮。
旋轉(zhuǎn)動(dòng)畫(huà)
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);
}
};
指針動(dòng)畫(huà)
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();
}
播放時(shí)啟動(dòng)旋轉(zhuǎn)動(dòng)畫(huà),播放指針動(dòng)畫(huà)帝洪,暫停時(shí)暫停動(dòng)畫(huà)似舵,播放指針動(dòng)畫(huà)。
OK葱峡,讓我們來(lái)看下效果
基本上和云音樂(lè)一樣的效果砚哗,而且可以自適應(yīng)屏幕大小,只是看不出來(lái)動(dòng)畫(huà)效果砰奕。
大家可以運(yùn)行源碼或下載波尼音樂(lè)查看詳細(xì)效果蛛芥。