Android语音声波控件 Android条形波控件
作者:长脸先生 发布时间:2023-10-29 02:03:05
标签:Android,声波控件,条形波控件
许久不来 , 冒个泡 , 发一个刚做的声音波动的View吧 :
代码不多 , 没什么技术含量 , 权当给您省时间了 , 直接复制粘贴就能用 , 直接上代码:
SoundWavesView
/**
* 语音通话的声波控件
* Created by Mr.LongFace on 2017/9/16.
*/
public class SoundWavesView extends View {
private int mMini; // 最短值
private int mMax; // 最大值
private int mLineWidth; // 每条声波的宽度
private int mSoundNum = 5; // 声波的数量
private int mSpac; // 每条声波的中点
private int mWidth , mHeight; // 控件宽高
private boolean isRun = false;
private Paint mPaint;
private RectF mRectF;
private List<SoundLine> mSoundList = new ArrayList<>();
private Handler mHandler = new Handler();
private Runnable mInvalidateRun = new Runnable() {
@Override
public void run() {
postInvalidate();
}
};
public SoundWavesView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(getResources().getColor(R.color.color_red));
mPaint.setStyle(Paint.Style.FILL);
mRectF = new RectF();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (widthMeasureSpec > 0 && heightMeasureSpec > 0) {
initParam();
}
}
private void initParam() {
mWidth = getWidth();
mHeight = getHeight();
mMini = (int) (mHeight * 0.3f);
mMax = mHeight;
initLines();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < mSoundNum; i++) {
SoundLine sound = mSoundList.get(i);
mRectF.left = sound.left;
mRectF.right = sound.right;
mRectF.top = sound.top;
mRectF.bottom = sound.bottom;
canvas.drawRoundRect(mRectF , mLineWidth / 2 , mLineWidth / 2 , mPaint);
}
if (isRun) {
mHandler.postDelayed(mInvalidateRun, 10);
}
}
@Override
protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
super.onVisibilityChanged(changedView, visibility);
if (isRun) {
if (visibility == VISIBLE) {
if (mWidth == 0) {
initParam();
}
if (mSoundList != null && mSoundList.size() > 0) {
for (SoundLine soundLine : mSoundList) {
soundLine.start();
}
}
}else{
if (mSoundList != null && mSoundList.size() > 0) {
for (SoundLine soundLine : mSoundList) {
soundLine.stop();
}
}
}
}
}
public void start() {
if (!isRun) {
isRun = true;
for (SoundLine sound : mSoundList) {
sound.start();
}
postInvalidate();
}
}
public void stop(){
if (isRun) {
isRun = false;
for (SoundLine sound : mSoundList) {
sound.stop();
}
}
}
private void initLines() {
mLineWidth = (int) (mWidth / mSoundNum * 0.7f);
mSpac = mWidth / (mSoundNum - 1);
mSoundList.clear();
chaos();
}
/**
* 生成凌乱的
*/
private void chaos() {
for (int i = 0; i < mSoundNum; i++) {
int left = i * mSpac - mLineWidth / 2;
int right = i * mSpac + mLineWidth / 2;
SoundLine s = new SoundLine(left , right , 0 , mHeight);
s.setMode(SoundLine.SPEED_RAN);
s.setBorder(mMini , mMax);
mSoundList.add(s);
}
}
/**
* 生成波浪的
*/
private void wave(){
// TODO 防止UI抽风
}
/**
* 生成有序的
*/
private void order(){
// TODO 防止UI抽风
}
}
SoundLine
/**
* 语音音频波纹的单个音波属性
* Created by Mr.LongFace on 2017/9/16.
*/
public class SoundLine implements ValueAnimator.AnimatorUpdateListener{
// 低 中 高 随机 4挡
public static final int SPEED_LOW = 500;
public static final int SPEED_MID = 200;
public static final int SPEED_HEI = 0;
public static final int SPEED_RAN = 0;
private Random mRandom;
private ValueAnimator mAnim;
public int left , right , top , bottom;
private int min , max;
public SoundLine(int left , int right , int top , int bottom){
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
mRandom = new Random();
initAnim();
}
private void initAnim() {
mAnim = ValueAnimator.ofFloat(0.0f , 1.0f);
setMode(SPEED_MID);
mAnim.setRepeatCount(-1);
mAnim.setRepeatMode(ValueAnimator.REVERSE);
mAnim.addUpdateListener(this);
}
public void setMode(int mode){
if (mode == SPEED_RAN) {
mode = mRandom.nextInt(400);
}
mAnim.setDuration(300 + mode);
}
public void start(){
if (mAnim.isRunning()){
mAnim.end();
}
mAnim.start();
}
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float f = (float) valueAnimator.getAnimatedValue();
top = (int) (f * (max - min) / 2);
bottom = max - top;
}
public void setBorder(int min, int max) {
this.min = min;
this.max = max;
}
public void stop() {
mAnim.end();
mAnim.cancel();
}
}
来源:http://blog.csdn.net/u012984054/article/details/78029578


猜你喜欢
- 本文实例为大家分享了C语言实现扫雷游戏的具体代码,供大家参考,具体内容如下此次扫雷中我们以9乘以9的表格为例,后期可自动调动主要思路:建立两
- 简介本文用示例介绍SpringBoot如何向容器注册bean(即:将对象加入容器)。法1:@Component(@Controller/@S
- Java 理解 ThreadLocal摘要: ThreadLocal 又名线程局部变量,是 Java 中一种较为特殊的线程绑定机制,用于保证
- 本文实例为大家分享了SpringBoot Http远程调用的具体代码,供大家参考,具体内容如下一、在实现远程调用时可以使用feign与htt
- Ctrl+1 快速修复Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ 复制当
- 一、前言本篇文章聚焦在“如何使用FragmentStatePagerAdapter来保存Fragment的数据、在内存中
- 一、关于idea中Maven的位置idea自带一个maven,其路径大致如下C:/java/IntelliJ IDEA 2020.1/plu
- 几种序列化技术:1)二进制序列化保持类型保真度,这对于在应用程序的不同调用之间保留对象的状态很有用。例如,通过将对象序列化到剪贴板,可在不同
- 一、场景笔者就Zuul网关下实现其负载均衡与熔断机制(雪崩)进行实践,前提是已经导入zuul相关依赖springboot版本:1.5.9.R
- 本文实例为大家分享了Android ViewPager实现页面左右切换的具体代码,供大家参考,具体内容如下主界面viewpager.xml:
- 1.object.toString()方法这种方法要注意的是object不能为null,否则会报NullPointException,一般别
- 因重定向无法正常goBack()解决方案首先说下问题,初始页面为A,点击某个链接跳转到B(http://xxx.com.cn/),B页面重定
- Android 动态菜单先上效果图比较简单,主要就是属性动画的使用和坐标角度的小细节。实现实现效果: 图标按照路径一路缩放渐变过来即可。核心
- 相信对于手机的时间日期设置大家一定都不陌生吧,今天举一个关于时间日期设置的示例,其中有些许不完善之处,例如如何使设置的时间日期和手机系统同步
- 前言fragment 可认为是一个轻量级的Activity,但不同与Activity,它是要嵌到Activity中来使用的,它用来解决设备屏
- import java.io.BufferedReader;import java.io.File;import java.io.FileI
- 先看效果图:(以公司附近的国贸为中心点)上面是地图,下面是地理位置列表,有的只有地理位置列表(QQ动态的位置),这是个很常见的功能。它有个专
- 一、 * 与过滤器在讲Spring boot之前,我们先了解一下过滤器和 * 。这两者在功能方面很类似,但是在具体技术实现方面,差距还是比较
- 问题描述:在windows系统下,idea中,操作terminal控制台,使用git log查看日志时,出现如下乱码为什么参考网上很多的gi
- 需求在前面的文章里使用.NET 6开发TodoList应用之领域实体创建原理和思路,我们留了一个坑还没有填上,就是在数据库保存的时