android 自定义音乐圆形进度条,Android自定义View实现音频播放圆形进度条
本篇文章介绍自定义View配合属性动画来实现如下的效果
实现思路如下:
根据播放按钮的图片大小计算出圆形进度条的大小
根据音频的时间长度计算出圆形进度条绘制的弧度
通过Handler刷新界面来更新圆形进度条的进度
具体实现过程分析:
首先来看看自定义View中定义的一些成员变量
//表示坐标系中的一块矩形区域
private RectF mRectF;
//画笔
private Paint mPaint;
//画笔宽度
private int mCircleStoreWidth = 3;
//最大进度值
private int mMaxProcessValue = 100;
//进度值
private int mProcessValue;
private int width;
private int height;
//播放器按钮id值
private int bitmapPlay;
private int bitmapStop;
//播放器按钮Bitmap对象
private Bitmap drawBitmapPlay;
private Bitmap drawBitmapStop;
private Context context;
//标记是否正在播放中
private boolean isPlay;
初始化自定义View,在这里获取播放器按钮图片以及初始化画布画笔对象以及设置将画笔设置抗锯齿
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
this.context = context;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.circle_progress_image_attrs);
bitmapPlay = a.getResourceId(R.styleable.circle_progress_image_attrs_play_image, R.mipmap.play_button);
bitmapStop = a.getResourceId(R.styleable.circle_progress_image_attrs_stop_image, R.mipmap.stop_button);
a.recycle();
drawBitmapPlay = BitmapFactory.decodeResource(context.getResources(), bitmapPlay);
drawBitmapStop = BitmapFactory.decodeResource(context.getResources(), bitmapStop);
mRectF = new RectF();
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
这里使用了自定义attrs来获取播放器按钮图片
在attrs.xml中新建如下:
然后在xml布局的自定义View中加入就能获取图片的id值了
circle:play_image="@mipmap/play_button"
circle:stop_image="@mipmap/stop_button"
然后我们重写onMeasure()来测量圆形进度条绘制的位置
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = measureWidth(widthMeasureSpec);
height = measureWidth(heightMeasureSpec);
mRectF.left = width / 2 - drawBitmapPlay.getWidth() / 2;
mRectF.top = height / 2 - drawBitmapPlay.getHeight() / 2;
mRectF.right = width / 2 + drawBitmapPlay.getWidth() / 2;
mRectF.bottom = height / 2 + drawBitmapPlay.getHeight() / 2;
}
public int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(specSize, result);
}
}
return result;
}
获取播放器按钮图片的大小后,计算出进度条的相应的坐标放入RectF对象中,RectF对象是用来表示坐标系中的一块矩形区域,用于在特定的位置画图
然后我们就可以通过重写onDraw()方法来绘制View了
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.TRANSPARENT);
//画圆
mPaint.setColor(ContextCompat.getColor(context, R.color.orange));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(mCircleStoreWidth);
// canvas.drawArc(mRectF, -90, 360, false, mPaint);
mPaint.setColor(ContextCompat.getColor(context, R.color.gray));
canvas.drawArc(mRectF, -90, ((float) mProcessValue / mMaxProcessValue) * 360, false, mPaint);
Log.d(TAG, ((float) mProcessValue / mMaxProcessValue) * 360 + "");
float imageLeft = width / 2 - drawBitmapPlay.getWidth() / 2;
float imageTop = height / 2 - drawBitmapPlay.getHeight() / 2;
if (isPlay) {
canvas.drawBitmap(drawBitmapStop, imageLeft, imageTop, mPaint);
} else {
canvas.drawBitmap(drawBitmapPlay, imageLeft, imageTop, mPaint);
}
}
要点其实就是canvas.drawArc()方法在RecfF的位置里画弧形,通过音频播放的开始时间/总时间*360来计算出弧度
要注意的是每次调用onDraw()方法的时候都需要先将canvas画透明色来起到清屏的作用
通过handler来每150毫秒刷新一次界面
private Handler handler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
//定时更新界面
if (isPlay) {
mProcessValue += 150;
if (mProcessValue == mMaxProcessValue) {
isPlay = false;
}
invalidate();
Message message = handler.obtainMessage(1);
handler.sendMessageDelayed(message, 150);
}
}
super.handleMessage(msg);
}
};
最后是一些包装方法,很简单不仔细介绍了
public void play() {
isPlay = true;
Message message = handler.obtainMessage(1);
handler.sendMessageDelayed(message, 150);
}
public void setDuration(int duration) {
this.mMaxProcessValue = duration;
}
public void clearDuration() {
this.mMaxProcessValue = 0;
this.mProcessValue = 0;
}
public void pause() {
isPlay = false;
invalidate();
}
public void stop() {
isPlay = false;
this.mMaxProcessValue = 0;
this.mProcessValue = 0;
invalidate();
}
音频播放的逻辑实现部分因为不属于自定义view因此可以自行参考demo
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
相关文章:

jsp error-page没有生效
1、首页检查web.xml中的配置,确保路径是正确的 <error-page> <error-code>404</error-code> <location>/error.jsp</location> </error-page> 2、然后再检查error.jsp文件内容是否有问题,比如只有<head>&…

CTO(首席技术官)
CTO(首席技术官)英文Chief Technology Officer,即企业内负责技术的最高负责人。这个名称在1980年代从美国开始时兴。起于做很多研究的大公司,如General Electric,AT&T,ALCOA,主要责任是将科…

把数组排成最小的数
题目 输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。 思路 一 需要找到字典序最小的哪个排列…

shell脚本自动执行,top命令无输出
shell脚本在系统启动时推后台自动执行,发现其中/usr/bin/top -n 1 -c -b -u ceph 命令并无输出 但是系统启动之后手动执行脚本,&推后台脚本中的top仍然能够正常输出,仅仅是系统发生重启,该功能就不生效了 stackoverflow 推荐…

0709 C语言常见误区----------函数指针问题
1.函数指针的定义 对于函数 void test(int a, int b){ // } 其函数指针类型是void (* ) (int , int), 注意这里第一个括号不能少, 定义一个函数指针,void (* pfunc)(int , int) ,其中pfunc就是函数指针类型, 它指向的函数类型必须…

android 定时换图片,android 视频和图片切换并进行自动轮播
刚入android没多久,遇到的比较郁闷的问题就是子线程主线程的问题,更改UI界面,本想做一个图片的轮播但是比较简单,然后就试试实现视频跟图片切换播放进行不停的循环播放。也用过不少控件,但是知其然不知其所以然&#x…

Win8:Snap 实现
Win8允许分屏的操作,所以我们必须让我们App能对Snap模式视图做出反应,这样也便于通过Store的审核。如果项目中在Snap展现的功能不大,我们可以仅用一张logo代替,类似系统的商店应用。 我的项目实现效果: 实现思路是在你…

ping命令使用及其常用参数
PING (Packet Internet Groper),因特网包探索器,用于测试网络连接量检查网络是否连通,可以很好地帮助我们分析和判定网络故障。Ping发送一个ICMP(Internet Control Messages Protocol)即因特网信报控制协议;回声请求消…

g-gdb工具使用图谱(持续更新)
如下为整个GDB的学习导图

android bitmap 转drawable,android Drawable转换成Bitmap失败
错误代码:08-07 06:42:30.482 28497-28497/app.tianxiayou E/AndroidRuntime﹕ FATAL EXCEPTION: mainProcess: app.tianxiayou, PID: 28497java.lang.RuntimeException: Unable to start activity ComponentInfo{app.tianxiayou/app.tianxiayou.AppInfoActivity}: …

微软职位内部推荐-Software Development Engineer II
微软近期Open的职位:Job Title:Software Development EngineerIIDivision: Server & Tools Business - Commerce Platform GroupWork Location: Shanghai, ChinaAre you looking for a high impact project that involves processing of billions of dollars, hundreds of …

Lync与Exchange 2013 UM集成:Exchange 配置
有点长时间没有更新文章了,也是由于工作的原因确实忙不过来,好在博客上还有这么多朋友支持,非常的欣慰啊。很久没有给大家带来新东西,真的非常抱歉,今天跟大家带来的是Lync Server 2013与Exchange Server 2013统一消息…
「Java基本功」一文读懂Java内部类的用法和原理
内部类初探 一、什么是内部类? 内部类是指在一个外部类的内部再定义一个类。内部类作为外部类的一个成员,并且依附于外部类而存在的。内部类可为静态,可用protected和private修饰(而外部类只能使用public和缺省的包访问权限&#…

从一致性hash到ceph crush算法演进图谱(持续更新)
参考文档: https://ceph.com/wp-content/uploads/2016/08/weil-crush-sc06.pdf Ceph剖析:数据分布之CRUSH算法与一致性Hash

[原]unity3d之http多线程异步资源下载
郑重声明:转载请注明出处 U_探索 本文诞生于乐元素面试过程,被面试官问到AssetBundle多线程异步下载时,愣了半天,同样也被深深的鄙视一回(做了3年多u3d 这个都没用过),所以发誓要实现出来填补一…

android首页图片轮播效果,Android_Android自动播放Banner图片轮播效果,先看一下效果图支持本地图 - phpStudy...
Android自动播放Banner图片轮播效果先看一下效果图支持本地图片以及网络图片or本地网络混合。使用方式:android:id"id/banner"android:layout_width"match_parent"android:layout_height"230dip">核心代码:int length …

mongodb 入门
在NOSQL的多个数据库版本中,mongodb相对比较成熟,把学mongodb笔记整理在这,方便以后回顾。这笔记预计分三部分: 一,基础操作,二、增删改查详细操作,三、高级应用。一、在linux在安装mongodb,在linux下安装m…

springboot 学习笔记(三)
(三)用jar包启动springboot项目 1、首先需要在pom文件中添加依赖,spring-boot-starter-parent包含有打包的默认配置,如果要修改的话要可以进行重新定义,具体内容参考https://docs.spring.io/spring-boot/docs/2.1.1.RE…

搜索:深搜/广搜 获取岛屿数量
题目描述: 用一个二维数组代表一张地图,这张地图由字符“0”与字符“1”组 成,其中“0”字符代表水域,“1”字符代表小岛土地,小岛“1”被 水“0”所包围,当小岛土地“1”在水平和垂直方向相连接时…

2.4.4.1、Django新建APP(acounts)
$django-admin.py startapp accounts 在oss/accounts修改forms.py(新建)和views.py如下: 注:绿字部分为注释 views.py ################################################################ #codingutf-8 from django.core.urlresolvers import reverse f…

vue html引入资源dev下404,webpack vue 项目打包生成的文件,资源文件报404问题的修复方法(总结篇)...
最近在使用webpack vue做个人娱乐项目时,发现npm run build后,css js img静态资源文件均找不到路径,报404错误。。。网上查找了一堆解决办法,总结如下一、首先修改config目录下的index.js文件将其中build的配置项assetsPublicPat…

解决.net webservice的WebClient或HttpWebRequest首次连接缓慢问题
【编程环境】Visual Studio 2010, NET4.0 【开发语言】C#, 理论上VB.NET等依赖.NET Framework框架的语言均受此影响 【问题描述】 使用HttpWebRequest抓取网页内容,但首次请求总是莫名奇妙的阻塞在Request.GetResponse();上,不过一旦这次请求成功,后续的操作就很快了…

2019-1-11
unique的使用: 1. unique是把相邻的重复元素放到最后面。所以在对无序数列使用之前,需要用sort先排序。 2.unique的返回值是不重复区的的最后一个元素加一的地址。 sort(V.begin(), V.end() ); vector<int>::iterator end_unique uniqueÿ…

搜索:广搜 词语阶梯
问题描述以及解决过程如下导图 广搜实现如下 #include <iostream> #include <algorithm> #include <vector> #include <string> #include <queue> #include <set> #include <map>using namespace std;/*判断两个单词是否有连接状态…

float属性html,详解CSS样式中的float属性
详解CSS样式中的float属性。float是 css样式的定位属性。我们在印刷排版中,文本可以按照需要围绕图片。一般把这种方式称为“文本环绕”。在网页设计中,应用了CSS的float属性的页面元素就像在印刷布局里面的被文字包围的图片一样。浮动的元素仍然是网页流…
机房收费系统系列一:运行时错误‘-2147217843(80040e4d)’;用户‘sa’登陆失败...
做机房收费系统的时候,首先在SQL server数据库中添加好charge数据库(在对象资源管理器中,右击数据库,点击附加,找到charge的mdf文件,点击确定),然后用ODBC配置好数据库,把…

JQuery新浪1630个表情插件
1.http://***/Detail.aspx?id131 2.http://***/Detail.aspx?id81转载于:https://www.cnblogs.com/zrp2013/archive/2013/05/17/3082961.html

linux open系统调用的O_DIRECT标记
前言 open系统调用中针对打开的文件描述符,可以增加一个O_DIRECT标记,该标记能够使得针对该文件描述符的写操作绕过操作系统page cache,直接进入通用块设备层,从而减少页缓存对IO效率的影响。 但是针对O_DIRECT标记有一个问题&a…

计算机专业每年都有国企招老吗,这十大专业在国企中最受欢迎,待遇高、前景好,有你的专业吗?...
古语说“三百六十行,行行出状元”这句话一点没错,但是当你报考传说中的“铁饭碗”、“金饭碗”的时候,你会发现,想入对行,首先你得选对专业,不管是对于报考还是以后的职业发展来说,选对专业和嫁…

实现一个基于 SharePoint 2013 的 Timecard 应用(下)
现在,基于 Timecard 数据来一点儿数据分析。 应用需求 对于 Timecard,分析下面 2 个方面: 对于单个项目,分析其中每个成员的工时占比,以此了解工作量分配,为组间人员调度提供参考。对于整个公司,…