Android 音频进度播放View(原View升级版)

Android 音频进度播放View(原View升级版)

描述:这是一个 声纹进度播放效果的Demo。

项目代码在最后面!!!!跳转到最后

控件效果如下:

此控件是基于之前的控件View加入了音频控制内容和跟随播放音乐进度显示进度
原仅控件文章可点击查看
在这里插入图片描述

实现功能:
  • 声纹可随机显示也可固定
  • 可自定义加载前后两种颜色
  • 可选择传入音乐进行播放,音乐播放进度和
  • 点击控件可控制音乐暂停和播放
设计核心:

主要的设计核心是依赖于drawRoundRect方法进行声纹条形的绘制,通过MediaPlay添加音乐播放和进度监听。

核心代码:

VoiceProgressView.java 一个声纹进度播放的自定义View 可直接载入layout

package com.ui.design.view.voicePorgress.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.MediaPlayer;
import android.media.TimedText;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 声纹显示View
 * tangxianfeng
 * 2021.12.19
 */

public class VoiceProgressView extends View {

    private int max = 0; //最大刻度

    private int mRectHeight = 0; //高度
    private int mRectWeight = 0; //宽度
    private Paint mAfterPaint;
    private Paint mBeforePaint;

    private int mBeforeProgress;//百分比
    private List<Integer> intArray = new ArrayList<>();//内置声纹长度

    private MediaPlayer mediaPlayer;

    private Timer timer;

    public VoiceProgressView(Context context) {
        this(context, null);
    }

    public VoiceProgressView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public VoiceProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        if (mAfterPaint == null) {
            mAfterPaint = new Paint();
            mAfterPaint.setColor(Color.parseColor("#356BD8"));
            mAfterPaint.setAntiAlias(true);
        }
        if (mBeforePaint == null) {
            mBeforePaint = new Paint();
            mBeforePaint.setColor(Color.parseColor("#ABC8F2"));
            mBeforePaint.setAntiAlias(true);
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mRectHeight == 0) {
            mRectHeight = getHeight();
        }
        if (mRectWeight == 0) {
            mRectWeight = getWidth();
        }
        if (max == 0) {
            max = mRectWeight / 16;
        }
        onDrawVoice(canvas); //画声纹
        super.onDraw(canvas);
    }

    /**
     * 画刻度
     */
    private void onDrawVoice(Canvas canvas) {
        if (intArray == null || intArray.size() == 0) {
            SecureRandom secureRandom = new SecureRandom();
            for (int i = 0; i < max + 1; i++) {
                int height = secureRandom.nextInt(40) + 15;
                intArray.add(height);
            }
        }//比实际声纹条数多一
        if (canvas == null) return;
        for (int i = 1; i < max; i++) {
            float height = intArray.get(i % intArray.size());
            //刻度间距
            int mScaleMargin = 16;
            canvas.drawRoundRect(i * mScaleMargin, (mRectHeight + height) / 2, i * mScaleMargin + 8, (mRectHeight - height) / 2, 5, 5, i < mBeforeProgress ? mAfterPaint : mBeforePaint);//播放前后的颜色替换
        }
    }


    //设置默认声纹 可传数组{20,25,38,19,40,25,30,38}
    public void setIntArray(List<Integer> intArray) {
        this.intArray = intArray;
    }

    //设置百分百
    public void setProgress(float progress) {
        Log.e("TEST",progress+"");
        if (progress > 100) {
            progress = 100;
        } else if (progress < 0) {
            progress = 0;
        }
        mBeforeProgress = (int) (max * progress / 100);
        postInvalidate();
    }

    //自定义声纹颜色 传入类型#356BD8
    public void initPaintColor(String beforecolor, String aftercolor) {
        if (!beforecolor.contains("#") || !aftercolor.contains("#")) {
            return;
        }//颜色格式需要含#号 简单判断处理下 不然会出错

        if (mAfterPaint != null) {
            mAfterPaint.setColor(Color.parseColor(beforecolor));
        }
        if (mBeforePaint != null) {
            mBeforePaint.setColor(Color.parseColor(aftercolor));
        }
    }

    //配置音乐
    public MediaPlayer configmusic() {
       mediaPlayer = new MediaPlayer();
        return mediaPlayer;
    }

    //初识化音乐
    public boolean initMusic(){
        if (mediaPlayer == null) {
            Log.e("VoiceView","mediaPlayer == null");
            return false;
        }
        try {
            mediaPlayer.prepare();
        } catch (IOException e) {
            e.printStackTrace();
            Log.e("VoiceView",e.getMessage());
            return false;
        }
        if (timer==null){
            timer=new Timer();
            TimerTask timerTask= new TimerTask() {
                @Override
                public void run() {
                    if (mediaPlayer != null) {
                        if (mediaPlayer.getCurrentPosition()==mediaPlayer.getDuration()){
                            setProgress(100);
                        }else {
                            // 将位置设置到当前播放位置
                            setProgress((float) mediaPlayer.getCurrentPosition() * 100 / mediaPlayer.getDuration());
                        }
                    }
                }
            };
            timer.schedule(timerTask,500,500);

            setOnClickListener(v -> {
                if (mediaPlayer.isPlaying()){
                    pause();
                }else {
                    play();
                }
            });
        }
        return true;
    }

    //播放
    public void play() {
        mediaPlayer.start();

    }

    //暂停播放
    public void pause() {
        mediaPlayer.pause();
    }

    //重置时间
    public void reset(){
        mediaPlayer.seekTo(0);
        mediaPlayer.pause();
        setProgress(0);
    }

    //销毁
    public void destory(){
        timer.cancel();
        mediaPlayer.release();
        mediaPlayer=null;
    }
}



使用示例:

VioceProgressActivity.java



import android.content.res.AssetFileDescriptor;
import android.widget.Button;
import android.widget.Toast;

import com.alibaba.android.arouter.facade.annotation.Route;
import com.ui.design.R;
import com.ui.design.main.base.BaseActivity;
import com.ui.design.main.constants.Constants;
import com.ui.design.view.voicePorgress.view.VoiceProgressView;

import java.io.IOException;

@Route(path = Constants.VioceProgressActivity)
public class VioceProgressActivity extends BaseActivity {

    private  VoiceProgressView voiceProgressView;

    @Override
    protected int initLayout() {
        return R.layout.activity_vioce_progress;
    }

    @Override
    protected void initView() {
        voiceProgressView = findViewById(R.id.voice_progress);
        Button play = findViewById(R.id.play);

        AssetFileDescriptor fd;
        try {
            fd = getAssets().openFd("test.mp3");
            voiceProgressView.configmusic().setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getLength());
            if (voiceProgressView.initMusic()) {
                Toast.makeText(this,"音乐载入成功",Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(this,"音乐载入失败",Toast.LENGTH_SHORT).show();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        play.setOnClickListener(v -> voiceProgressView.reset());
    }


    @Override
    protected void onDestroy() {
        voiceProgressView.destory();
        super.onDestroy();
    }

    @Override
    protected void initData() {

    }
}

layout:voice_progress.xml

 <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".view.voicePorgress.VioceProgressActivity">

    <include
        android:id="@+id/include2"
        layout="@layout/title_include" />

    <androidx.appcompat.widget.AppCompatTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@color/grey"
        android:layout_gravity="center"
        android:layout_marginTop="180dp"
        android:text="点击图案可进行播放"/>
    <com.ui.design.view.voicePorgress.view.VoiceProgressView
        android:id="@+id/voice_progress"
        android:layout_width="250dp"
        android:layout_gravity="center"
        android:layout_height="40dp"
        android:layout_marginTop="20dp"/>

    <androidx.appcompat.widget.AppCompatButton
        android:id="@+id/play"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="40dp"
        android:text="重置"/>
</LinearLayout>

项目代码仓库

如果直接复制可能会出现代码缺陷,完整代码请去仓库下载
如果觉得还行,耽误您几秒钟的时间去我的仓库点点star,万一以后用到了呢?

UIDesign 开源项目

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值