Android实现音频条形图效果(仿音频动画无监听音频输入)

音频条形图

如下图所示就是这次的音频条形图:

由于只是自定义View的用法,我们就不去真实地监听音频输入了,随机模拟一些数字即可。

如果要实现一个如上图的静态音频条形图,相信大家应该可以很快找到思路,也就是绘制一个个的矩形,每个矩形之间稍微偏移一点距离即可。如下代码就展示了一种计算坐标的方法。

for (int i = 0; i < mRectCount; i++) { // 矩形的绘制是从左边开始到上、右、下边(左右边距离左边画布边界的距离,上下边距离上边画布边界的距离) canvas.drawRect( (float) (mRectWidth * i + offset), currentHeight, (float) ( mRectWidth * (i + 1)), mRectHeight, mRectPaint ); }

如上代码中,我们通过循环创建这些小的矩形,其中currentHeight就是每个小矩形的高,通过横坐标的不断偏移,就绘制出了这些静态的小矩形。下面再通过矩形的高度随机变化模拟音频,这里直接利用Math.randoom()方法来随机改变这些高度,并赋值给currentHeight,代码如下所示。

// 由于只是简单的案例就不监听音频输入,随机模拟一些数字即可 mRandom = Math.random(); currentHeight = (float) (mRectHeight * mRandom);

这样就能实现静态效果了,但是如何实现动态效果呢?其实也是非常简单的,只要在onDraw()方法中再去调用invalidate()方法通知View进行重绘就可以了。不过这里不需要每次一绘制完新的矩形就通知View进行重绘,这样会因为刷新速度太快反而影响效果。因此,我们可以使用如下代码来进行View的延迟重绘,代码如下:

posInvalidateDelayed(300);

这样每隔300ms通知View进行重绘,就可以得到一个比较好的视觉效果了。最后添加一个渐变效果可以使View更加逼真,代码如下所示:

@Override protected void onSizeChanged(int w,int h,int oldW,int oldH) { super.onSizeChanged(w, h, oldW, oldH); // 渐变效果 LinearGradient mLinearGradient; // 画布的宽 int mWidth; // 获取画布的宽 mWidth = getWidth(); // 获取矩形的最大高度 mRectHeight = getHeight(); // 获取单个矩形的宽度(减去的部分为到右边界的间距) mRectWidth = (mWidth-offset) / mRectCount; // 实例化一个线性渐变 mLinearGradient = new LinearGradient( 0, 0, mRectWidth, mRectHeight, topColor, downColor, Shader.TileMode.CLAMP ); // 添加进画笔的着色器 mRectPaint.setShader(mLinearGradient); }

从这个例子中,我们可以知道,在创建自定义View的时候,需要一步一步来,从一个基本的效果开始,慢慢地添加功能,绘制更复杂的效果。不论是多么复杂的自定义View都一定是慢慢迭代起来的功能,所以不要觉得自定义View有多难。千里之行始于足下,只要开始做,慢慢地就能越来越熟练。

代码

以下是这次的完整代码:

package com.example.customaf; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Shader; import android.support.v4.content.ContextCompat; import android.util.AttributeSet; import android.view.View; import com.example.afanalog.R; /** * 自定义的音频模拟条形图 * Created by shize on 2016/9/5. */ public class MyAF extends View { // 音频矩形的数量 private int mRectCount; // 音频矩形的画笔 private Paint mRectPaint; // 渐变颜色的两种 private int topColor, downColor; // 音频矩形的宽和高 private int mRectWidth, mRectHeight; // 偏移量 private int offset; // 频率速度 private int mSpeed; public MyAF(Context context) { super(context); } public MyAF(Context context, AttributeSet attrs) { super(context, attrs); setPaint(context, attrs); } public MyAF(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setPaint(context, attrs); } public void setPaint(Context context, AttributeSet attrs){ // 将属性存储到TypedArray中 TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.MyAF); mRectPaint = new Paint(); // 添加矩形画笔的基础颜色 mRectPaint.setColor(ta.getColor(R.styleable.MyAF_AFTopColor, ContextCompat.getColor(context, R.color.top_color))); // 添加矩形渐变色的上面部分 topColor=ta.getColor(R.styleable.MyAF_AFTopColor, ContextCompat.getColor(context, R.color.top_color)); // 添加矩形渐变色的下面部分 downColor=ta.getColor(R.styleable.MyAF_AFDownColor, ContextCompat.getColor(context, R.color.down_color)); // 设置矩形的数量 mRectCount=ta.getInt(R.styleable.MyAF_AFCount, 10); // 设置重绘的时间间隔,也就是变化速度 mSpeed=ta.getInt(R.styleable.MyAF_AFSpeed, 300); // 每个矩形的间隔 offset=ta.getInt(R.styleable.MyAF_AFOffset, 5); // 回收TypeArray ta.recycle(); } @Override protected void onSizeChanged(int w,int h,int oldW,int oldH) { super.onSizeChanged(w, h, oldW, oldH); // 渐变效果 LinearGradient mLinearGradient; // 画布的宽 int mWidth; // 获取画布的宽 mWidth = getWidth(); // 获取矩形的最大高度 mRectHeight = getHeight(); // 获取单个矩形的宽度(减去的部分为到右边界的间距) mRectWidth = (mWidth-offset) / mRectCount; // 实例化一个线性渐变 mLinearGradient = new LinearGradient( 0, 0, mRectWidth, mRectHeight, topColor, downColor, Shader.TileMode.CLAMP ); // 添加进画笔的着色器 mRectPaint.setShader(mLinearGradient); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); double mRandom; float currentHeight; for (int i = 0; i < mRectCount; i++) { // 由于只是简单的案例就不监听音频输入,随机模拟一些数字即可 mRandom = Math.random(); currentHeight = (float) (mRectHeight * mRandom); // 矩形的绘制是从左边开始到上、右、下边(左右边距离左边画布边界的距离,上下边距离上边画布边界的距离) canvas.drawRect( (float) (mRectWidth * i + offset), currentHeight, (float) ( mRectWidth * (i + 1)), mRectHeight, mRectPaint ); } // 使得view延迟重绘 postInvalidateDelayed(mSpeed); } }

布局文件的完整代码:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:custom="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.example.afanalog.MainActivity"> <com.example.customaf.MyAF android:layout_width="match_parent" android:layout_height="match_parent" custom:AFCount="15" custom:AFDownColor="@color/down_color" custom:AFSpeed="300" custom:AFTopColor="@color/top_color" custom:AFOffset="15" /> </LinearLayout>

以上所述是小编给大家介绍的Android实现音频条形图效果(仿音频动画无监听音频输入),希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

时间: 2024-11-09 02:11:00

Android实现音频条形图效果(仿音频动画无监听音频输入)的相关文章

item长按监听-Android ActionBar中Action按钮怎么设置长按监听?

问题描述 Android ActionBar中Action按钮怎么设置长按监听? 如题. 或者是滑动监听,只要是和单机区分开就好,不知哪位大神以前做过这个? 解决方案 如果有按下/抬起事件,而不是只有Click事件,就可以考虑自己实现长按的功能. 否则,就只能放弃:或者,自定义按键来实现类似的功能. 解决方案二: 如果有按下/抬起事件,而不是只有Click事件,就可以考虑自己实现长按的功能. 否则,就只能放弃:或者,自定义按键来实现类似的功能.

Android Input子系统:Input进程的创建,监听线程的启动

本文讲的是Android Input子系统:Input进程的创建,监听线程的启动,本文主要从系统源码的角度带你一步步了解Android Input子系统. 从我个人的理解来看,Android的Input系统其实就是系统级的事件处理.分发框架,它需要的功能模块大致有:事件读取.事件分类.事件分发.那么我们就从整个Input系统的输入源入手,了解事件是如何被输入到Input系统中的. 在看代码前我们先想一想,如果要我们设计一个事件分发框架的输入读取模块,要考虑到哪些子模块: 事件生成模块(当用户对设

Android开发中给EditText控件添加TextWatcher监听实现对输入字数的限制(推荐)_Android

 做这个功能是因为开发项目的时候,由于后台接口的一些参数的值的长度有要求,不能超过多少个字符,所以在编辑框中输入的字符是要有限制的. 下面就来看一下demo的实现过程: 首先,在xml控件中放置一个EditText控件,然后初始化该控件并对该控件添加文本监听.xml自己简单的设计一下,代码较为简单,直接上代码: package com.example.edittext; import android.app.Activity; import android.os.Bundle; import a

Android编程双重单选对话框布局实现与事件监听方法示例

本文实例讲述了Android编程双重单选对话框布局实现与事件监听方法.分享给大家供大家参考,具体如下: 首先是自定义XML布局代码: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_pare

Android关于Glide的使用(高斯模糊、加载监听、圆角图片)_Android

高斯模糊.加载监听.圆角图片这些相信大家都很熟悉,那如何实现这些效果,请大家参考本文进行学习. 1.引用 compile 'com.github.bumptech.glide:glide:3.7.0' 2.加载图片 2.1 基本加载 Glide.with(context)     .load(url)     .into(imageView); 2.2 设置加载中和加载失败的情况 Glide.with(context) .load(url) .placeholder(R.drawable.loa

Android关于Glide的使用(高斯模糊、加载监听、圆角图片)

高斯模糊.加载监听.圆角图片这些相信大家都很熟悉,那如何实现这些效果,请大家参考本文进行学习. 1.引用 compile 'com.github.bumptech.glide:glide:3.7.0' 2.加载图片 2.1 基本加载 Glide.with(context)     .load(url)     .into(imageView); 2.2 设置加载中和加载失败的情况 Glide.with(context) .load(url) .placeholder(R.drawable.loa

Android中GIF动图的播放控制和监听详解

前言 最近接手的项目里涉及到了 GIF 动图的播放与监听,在上一版本中对于 GIF 的处理是由 H5 来实现的,因为考虑到用户体验,因此现在的需求是将这块儿原生化,途中差点误入歧途!下面来看看详细的介绍吧. Android 中 GIF 动图处理与监听 刚开始第一个想到的便是 glide , 但是自认为 glide 不能够控制 GIF 以及去监听它,所以网上去搜寻别的方法.看到有一个方案是将图片分帧,一张张的去用逐帧动画来实现. 我开始怀疑给这个解决方案的人了,都什么时代了还做这种费力不讨好,大量

安卓(Android)动态创建多个按钮并添加监听事件_Android

1.获取屏幕大小,以合理设定 按钮 大小及位置 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int width = dm.widthPixels; int height = dm.heightPixels; 2.自定义layout组件 RelativeLayout layout = new RelativeLayout(this); 3.这里创建1

安卓(Android)动态创建多个按钮并添加监听事件

1.获取屏幕大小,以合理设定 按钮 大小及位置 DisplayMetrics dm = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(dm); int width = dm.widthPixels; int height = dm.heightPixels; 2.自定义layout组件 RelativeLayout layout = new RelativeLayout(this); 3.这里创建1