android实现音乐跳动效果的示例代码
效果图
实现
整体的流程图如下
上面主要步骤分为3个
1、计算宽度能放下多少列的音频块。
2、计算每一列中音频块的个数
3、绘制音频块
1、计算宽度能放下多少列的音频块。
设置音频块的宽度为danceWidth,音频块横向之间的间距为danceGap,那么可以算出能放的列数:
/** * 先计算当前宽度能够放下多少个音频块 */ val widthNum = (getAvailableWith() / (danceGap + danceWidth)).toInt() /** * 获取可以用的宽度 */ private fun getAvailableWith() = mCanvasWidth - paddingLeft - paddingRight
2、计算每一列中音频块的个数
在算出横向能放置多少音频块后,遍历横,然后绘制列中的音频块,列中的音频块的个数跟音频的高低相关,这里实现方式是通过Visualizer这个类然后获取到mRawAudioBytes数组,
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);
这里设置的获取的mRawAudioBytes数组的大小是128,数组的区间范围[-128,127],计算列的时候这里做了两个比较重要的操作,第一个是怎么把mRawAudioBytes数组的值与音频的个数做映射,第二个是怎么取mRawAudioBytes数组的值。
/** * 先计算当前宽度能够放下多少个音频块 */ val widthNum = (getAvailableWith() / (danceGap + danceWidth)).toInt() Log.d( TAG, "widthNum $widthNum" ) /** * 算出横向能放多少后,进行绘制 */ /** * 绘制的时候用于标记开始绘制的位置 */ var lastDanceRight = paddingLeft.toFloat() if (widthNum > 0 && mRawAudioBytes != null && mRawAudioBytes.isNotEmpty()) for (i in 0 until widthNum) { //先算出当前高度,然后再算这个高度能放下多少个音频块 val num = (getAvailableHeight() / (danceHeight + danceGap)).toInt() val index = (mRawAudioBytes.size) * (i.toFloat() / widthNum) val b = (mRawAudioBytes[index.toInt()] + 128).toFloat() / 255f var 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 }
上面做了两个映射,首先可能有0~n横,但是mRawAudioBytes大小是128,遍历横的时候对下标进行一个映射,保证获得的值是均匀的,
/** 通过这个映射得到index */ val index = (mRawAudioBytes.size) * (i.toFloat() / widthNum)
第二个映射,是得到了代表音频大小的mRawAudioBytes数组,现在要把这里面的值跟列的高度做一个映射,值越大高度越高,音频块就越多。
val num = (getAvailableHeight() / (danceHeight + danceGap)).toInt() val b = (mRawAudioBytes[index.toInt()] + 128).toFloat() / 255f var heightNum =(b * num).toInt()
上面是先得到列最多能展示多少音频块,再根据mRawAudioBytes的值来算出当前列展示多少个音频块。这一步也叫归一化,区间映射。
3、绘制每一个音频块
private fun drawItem( heightNum: Int, lastDanceRight: Float, lastHeight: Float, canvas: Canvas? ): Float { var lastHeight1 = lastHeight for (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 }
就是根据高度来绘制rectangle,算出一列能绘制多少个音频块,每一个音频块是一个rectangle,然后绘制rectangle,为了效果更好,判断上面的音频块加上渐变。
使用方法
<com.masoudss.lib.DanceView android:id="@+id/danceView" 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 顶部加渐变的个数
- color_end 渐变尾部颜色
- color_start 渐变开头颜色
- color_center 渐变中间颜色
- min_dance_num 每一列中最少显示的个数
- max_dance_num 每一列中最大显示的个数
- dance_gap 每一个音频格之间的间距
栏 目:Android代码
下一篇:Android ListView实现下拉顶部图片变大效果
本文标题:android实现音乐跳动效果的示例代码
本文地址:http://www.codeinn.net/misctech/188900.html