android實(shí)現(xiàn)音樂(lè)跳動(dòng)效果的示例代碼
整體的流程圖如下
上面主要步驟分為3個(gè)1、計(jì)算寬度能放下多少列的音頻塊。2、計(jì)算每一列中音頻塊的個(gè)數(shù)3、繪制音頻塊
1、計(jì)算寬度能放下多少列的音頻塊。設(shè)置音頻塊的寬度為danceWidth,音頻塊橫向之間的間距為danceGap,那么可以算出能放的列數(shù):
/** * 先計(jì)算當(dāng)前寬度能夠放下多少個(gè)音頻塊 */val widthNum = (getAvailableWith() / (danceGap + danceWidth)).toInt() /** * 獲取可以用的寬度 */ private fun getAvailableWith() = mCanvasWidth - paddingLeft - paddingRight2、計(jì)算每一列中音頻塊的個(gè)數(shù)
在算出橫向能放置多少音頻塊后,遍歷橫,然后繪制列中的音頻塊,列中的音頻塊的個(gè)數(shù)跟音頻的高低相關(guān),這里實(shí)現(xiàn)方式是通過(guò)Visualizer這個(gè)類(lèi)然后獲取到mRawAudioBytes數(shù)組,
mVisualizer.setDataCaptureListener(new Visualizer.OnDataCaptureListener() { @Override public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {BaseVisualizer.this.mRawAudioBytes = bytes;invalidate(); } @Override public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) { }}, Visualizer.getMaxCaptureRate() / 2, true, false);
這里設(shè)置的獲取的mRawAudioBytes數(shù)組的大小是128,數(shù)組的區(qū)間范圍[-128,127],計(jì)算列的時(shí)候這里做了兩個(gè)比較重要的操作,第一個(gè)是怎么把mRawAudioBytes數(shù)組的值與音頻的個(gè)數(shù)做映射,第二個(gè)是怎么取mRawAudioBytes數(shù)組的值。
/** * 先計(jì)算當(dāng)前寬度能夠放下多少個(gè)音頻塊 */val widthNum = (getAvailableWith() / (danceGap + danceWidth)).toInt()Log.d( TAG, 'widthNum $widthNum')/** * 算出橫向能放多少后,進(jìn)行繪制 *//** * 繪制的時(shí)候用于標(biāo)記開(kāi)始繪制的位置 */var lastDanceRight = paddingLeft.toFloat()if (widthNum > 0 && mRawAudioBytes != null && mRawAudioBytes.isNotEmpty()) for (i in 0 until widthNum) {//先算出當(dāng)前高度,然后再算這個(gè)高度能放下多少個(gè)音頻塊val num = (getAvailableHeight() / (danceHeight + danceGap)).toInt()val index = (mRawAudioBytes.size) * (i.toFloat() / widthNum)val b = (mRawAudioBytes[index.toInt()] + 128).toFloat() / 255fvar heightNum = (b * num).toInt()if (heightNum < miniNum) { heightNum = miniNum}if (heightNum > maxNum) { heightNum = maxNum}//拿到最頂部的高度var lastHeight = mCanvasHeight - paddingStart.toFloat()Log.d( TAG, 'heightNum $heightNum lastHeight $lastHeight lastDanceRight $lastDanceRight ${mRawAudioBytes[i]} $num $b $index')lastHeight = drawItem(heightNum, lastDanceRight, lastHeight, canvas)lastDanceRight += danceWidth + danceGap }
上面做了兩個(gè)映射,首先可能有0~n橫,但是mRawAudioBytes大小是128,遍歷橫的時(shí)候?qū)ο聵?biāo)進(jìn)行一個(gè)映射,保證獲得的值是均勻的,
/**通過(guò)這個(gè)映射得到index*/val index = (mRawAudioBytes.size) * (i.toFloat() / widthNum)
第二個(gè)映射,是得到了代表音頻大小的mRawAudioBytes數(shù)組,現(xiàn)在要把這里面的值跟列的高度做一個(gè)映射,值越大高度越高,音頻塊就越多。
val num = (getAvailableHeight() / (danceHeight + danceGap)).toInt()val b = (mRawAudioBytes[index.toInt()] + 128).toFloat() / 255fvar heightNum =(b * num).toInt()
上面是先得到列最多能展示多少音頻塊,再根據(jù)mRawAudioBytes的值來(lái)算出當(dāng)前列展示多少個(gè)音頻塊。這一步也叫歸一化,區(qū)間映射。
3、繪制每一個(gè)音頻塊private fun drawItem(heightNum: Int,lastDanceRight: Float,lastHeight: Float,canvas: Canvas? ): Float {var lastHeight1 = lastHeightfor (j in 0 until heightNum) { mDanceRect.set(lastDanceRight,lastHeight1 - danceHeight,lastDanceRight + danceWidth,lastHeight1 ) mPaint.shader = null if (j >= heightNum - shaderNum) {val backGradient = LinearGradient( lastDanceRight, lastHeight1 - danceHeight, lastDanceRight + danceWidth, lastHeight1, intArrayOf(colorStart, colorCenter, colorEnd), null, Shader.TileMode.CLAMP)mPaint.shader = backGradient } canvas?.drawRoundRect(mDanceRect, 8f, 8f, mPaint) lastHeight1 -= (danceHeight + danceGap)}return lastHeight1 }
就是根據(jù)高度來(lái)繪制rectangle,算出一列能繪制多少個(gè)音頻塊,每一個(gè)音頻塊是一個(gè)rectangle,然后繪制rectangle,為了效果更好,判斷上面的音頻塊加上漸變。
github地址
使用方法
<com.masoudss.lib.DanceView android: android:layout_width='320dp' android:layout_height='300dp' android:layout_gravity='center' app:color_center='@color/red' app:color_end='@color/white' app:color_start='@color/yellow' app:dance_color='@color/yellow' app:dance_corner_radius='2dp' app:dance_gap='2dp' app:max_dance_num='30' app:min_dance_num='2' app:shader_num='3' /> shader_num 頂部加漸變的個(gè)數(shù) color_end 漸變尾部顏色 color_start 漸變開(kāi)頭顏色 color_center 漸變中間顏色 min_dance_num 每一列中最少顯示的個(gè)數(shù) max_dance_num 每一列中最大顯示的個(gè)數(shù) dance_gap 每一個(gè)音頻格之間的間距
到此這篇關(guān)于android實(shí)現(xiàn)音樂(lè)跳動(dòng)效果的示例代碼的文章就介紹到這了,更多相關(guān)android 音樂(lè)跳動(dòng)內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. UDDI FAQs2. python 批量下載bilibili視頻的gui程序3. 詳解CSS偽元素的妙用單標(biāo)簽之美4. python numpy庫(kù)np.percentile用法說(shuō)明5. PHP 面向?qū)ο蟪绦蛟O(shè)計(jì)之類(lèi)屬性與類(lèi)常量實(shí)現(xiàn)方法分析6. HTML <!DOCTYPE> 標(biāo)簽7. CSS自定義滾動(dòng)條樣式案例詳解9. Java Spring WEB應(yīng)用實(shí)例化如何實(shí)現(xiàn)10. 將properties文件的配置設(shè)置為整個(gè)Web應(yīng)用的全局變量實(shí)現(xiàn)方法
