基于鸿洋博客自定于View实现的android音量调节控件

1.在values建立attrs.xml,写出你需要的属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="firstColor" format="color" />
<attr name="secondColor" format="color" />
<attr name="circleWidth" format="dimension" />
<attr name="dotCount" format="integer" />
<attr name="splitSize" format="integer" />
<attr name="bg" format="reference" /> <declare-styleable name="CustomVolumControlBar">
<attr name="firstColor" />
<attr name="secondColor" />
<attr name="circleWidth" />
<attr name="dotCount" />
<attr name="splitSize" />
<attr name="bg" />
</declare-styleable> </resources>
2.创建view类并实现所需要的业务,具体看代码,代码中写的很详细:
package com.zzw.Custom.widget; import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.media.AudioManager;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View; import com.zzw.Custom.R; /**
* Created by zzw on 2016/6/1.
* 描述:
*/
public class CustomVolumControlBar extends View { /**
* 第一圈的颜色
*/
private int mFirstColor; /**
* 第二圈的颜色
*/
private int mSecondColor;
/**
* 圈的宽度
*/
private int mCircleWidth;
/**
* 画笔
*/
private Paint mPaint;
/**
* 当前进度
*/
private int mCurrentCount = 3; /**
* 中间的图片
*/
private Bitmap mImage;
/**
* 每个块块间的间隙
*/
private int mSplitSize;
/**
* 个数
*/
private int mCount; /**
* 中间图片界限
*/
private Rect mRect; private AudioManager mAudioManager; private Handler mHandler = new Handler(); public CustomVolumControlBar(Context context) {
this(context, null);
} public CustomVolumControlBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
} public CustomVolumControlBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
} private void init(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomVolumControlBar, defStyleAttr, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.CustomVolumControlBar_firstColor:
this.mFirstColor = a.getColor(attr, Color.BLACK);
break; case R.styleable.CustomVolumControlBar_secondColor:
this.mSecondColor = a.getColor(attr, Color.WHITE);
break; case R.styleable.CustomVolumControlBar_circleWidth:
this.mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));
break; case R.styleable.CustomVolumControlBar_dotCount:
this.mCount = a.getInt(attr, 20);// 默认20
break; case R.styleable.CustomVolumControlBar_splitSize:
this.mSplitSize = a.getInt(attr, 20);
break; case R.styleable.CustomVolumControlBar_bg:
this.mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));
break;
}
}
a.recycle();
mPaint = new Paint();
mRect = new Rect();
if (mAudioManager == null)
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); /**
* 获取到最大音量和当前音量
*/
mCount = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
mCurrentCount = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); Log.e("=====", "mCount:" + mCount + " mCurrentCount:" + mCurrentCount);
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); mPaint.setAntiAlias(true);//消除锯齿
mPaint.setStrokeWidth(mCircleWidth);//设置圆圈宽度
mPaint.setStrokeCap(Paint.Cap.ROUND);//定义线段电形状圆头
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);//设置空心
int centre = getWidth() / 2;//得到圆心
int radius = centre - mCircleWidth / 2;//得到半径 drawOval(canvas, centre, radius); /**
* 计算内切正方形的位置
*/
int relRadius = radius - mCircleWidth / 2;// 获得内圆的半径
/**
* 内切正方形的距离顶部 = mCircleWidth + relRadius - √2 / 2
*/
mRect.left = (int) (relRadius - Math.sqrt(2) * 1.0f / 2 * relRadius) + mCircleWidth; /**
* 内切正方形的距离左边 = mCircleWidth + relRadius - √2 / 2
*/
mRect.top = (int) (relRadius - Math.sqrt(2) * 1.0f / 2 * relRadius) + mCircleWidth; mRect.bottom = (int) (mRect.left + Math.sqrt(2) * relRadius);
mRect.right = (int) (mRect.left + Math.sqrt(2) * relRadius); /**
* 如果图片比较小,那么根据图片的尺寸放置到正中心
*/
if (mImage.getWidth() < Math.sqrt(2) * relRadius) {
mRect.left = (int) (mRect.left + Math.sqrt(2) * relRadius * 1.0f / 2 - mImage.getWidth() * 1.0f / 2);
mRect.top = (int) (mRect.top + Math.sqrt(2) * relRadius * 1.0f / 2 - mImage.getHeight() * 1.0f / 2);
mRect.right = (int) (mRect.left + mImage.getWidth());
mRect.bottom = (int) (mRect.top + mImage.getHeight());
}
// 绘图
canvas.drawBitmap(mImage, null, mRect, mPaint);
} /**
* 画块块去
*/
private void drawOval(Canvas canvas, int centre, int radius) { /**
* 根据需要画的个数以及间隙计算每个块块所占的比例*360
*/
float itemSize = (360 * 1.0f - mCount * mSplitSize) / mCount;
/**
* 用于定义的圆弧的形状和大小的界限
*/
RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius);
mPaint.setColor(mFirstColor);// 设置圆环的颜色
for (int i = 0; i < mCount; i++) {
canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint);// 根据进度画圆弧
}
mPaint.setColor(mSecondColor); // 设置圆环的颜色
for (int i = 0; i < mCurrentCount; i++) {
canvas.drawArc(oval, i * (itemSize + mSplitSize), itemSize, false, mPaint); // 根据进度画圆弧
}
} /**
* 当前数量+1
*/
public synchronized void up() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mCurrentCount++;
if (mCurrentCount > mCount)
mCurrentCount = mCount; postInvalidate();
setVolume(mCurrentCount);
}
}, 100);
} /**
* 设置音量
*
* @param index
*/
private void setVolume(int index) {
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, index, 1);
} /**
* 当前数量-1
*/
public synchronized void down() {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mCurrentCount--;
if (mCurrentCount < 0)
mCurrentCount = 0;
postInvalidate();
setVolume(mCurrentCount);
}
}, 100);
} private int lastY, nowY; @Override
public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = (int) event.getY();
break; case MotionEvent.ACTION_MOVE:
nowY = (int) event.getY();
int updateYCount = (nowY - lastY) / 30;
if (updateYCount > 0) {
for (int i = 0; i < updateYCount; i++) {
down();
}
} else if (updateYCount < 0) {
for (int i = updateYCount; i < 0; i++) {
up();
}
}
lastY = nowY;
break;
}
return true;
}
}
3.在xml中引用:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context="com.zzw.Custom.MainActivity"> <com.zzw.Custom.widget.CustomVolumControlBar
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerInParent="true"
app:bg="@mipmap/ic_horn"
app:circleWidth="5dp"
app:firstColor="@color/colorPrimary"
app:secondColor="@color/colorAccent"
app:splitSize="10" />
</RelativeLayout>
当然,在实际操作中OnTouch事件一般是放在activity或者Fragment里面的,只需在代码中复制出去即可
最后十分感谢鸿洋大神,让我们学到了很多,该篇与鸿洋大神相关的的博客地址:http://blog.csdn.net/lmj623565791/article/details/24529807
CustomVolumControlBar
基于鸿洋博客自定于View实现的android音量调节控件的更多相关文章
- 基于.NetCore开发博客项目 StarBlog - (6) 页面开发之博客文章列表
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (7) 页面开发之文章详情页面
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (8) 分类层级结构展示
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (12) Razor页面动态编译
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (16) 一些新功能 (监控/统计/配置/初始化)
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 基于.NetCore开发博客项目 StarBlog - (17) 自动下载文章里的外部图片
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 象写程序一样写博客:搭建基于github的博客
象写程序一样写博客:搭建基于github的博客 前言 github 真是无所不能.其 Pages 功能 支持上传 html,并且在页面中显示.于是有好事者做了一个基于 github 的博客管理工具 ...
- Lucene5.5.4入门以及基于Lucene实现博客搜索功能
前言 一直以来个人博客的搜索功能很蹩脚,只是自己简单用数据库的like %keyword%来实现的,所以导致经常搜不到想要找的内容,而且高亮显示.摘要截取等也不好实现,所以决定采用Lucene改写博客 ...
- 基于Hexo搭建博客并部署到Github Pages
基于Hexo搭建博客并部署到Github Pages 之前在简书上写东西,觉得自己还是太浮躁.本来打算用Flask自己写一个,以为是微框架就比较简单,naive.HTML.CSS.JS等都要学啊,我几 ...
随机推荐
- hive 安装警告 WARN conf.HiveConf: HiveConf of name hive.metastore.local does not exist
解决方法: 在0.10 0.11或者之后的HIVE版本 hive.metastore.local 属性不再使用. 在配置文件里面: <property> <name>hi ...
- (1)虚拟机的安装与使用,linux系统安装
一.百度下载 VMware workStation 二.新建虚拟机 在这里分为典型和自定义,典型及许多磁盘类型及接口类型为默认,自定义高级则可以都做选择设置. 三.自定义(高级)安装 (1)点击下一步 ...
- [转载]MySQL concat函数的使用
MySQL concat函数是MySQL数据库中众多的函数之一,下文将对MySQL concat函数的语法和使用进行说明,供您参考和学习. MySQL concat函数使用方法:CONCAT(str1 ...
- Parquet and ORC
http://dongxicheng.org/mapreduce-nextgen/columnar-storage-parquet-and-orc/ 相比传统的行式存储引擎,列式存储引擎具有更高的压缩 ...
- jpa,jdbc,hibernate/mybatis,数据库驱动
JPA是规范,hibernate/mybatis是对规范的实现,hibernate/mybatis是对jdbc的封装,也就是说hibernate/mybatis还是会调用jdbc. 我们平时使用 ...
- zookeeper部署搭建
zookeeper教程 1.先在linux系统中安装jdk并配置环境变量,可以参考下面的链接1 2.下载安装zookeeper软件 教程参考: 链接1:http://www.linuxidc.com/ ...
- XML文件结构和基本语法
XML文件的结构性内容,包括节点关系以及属性内容等等.元素是组成XML的最基本的单位,它由开始标记,属性和结束标记组成.就是一个元素的例子,每个元素必须有一个元素名,元素可以若干个属性以及属性值. x ...
- qt的udp的初步使用(转)
该程序实现的功能是:局域网内,每个用户登录到聊天软件,则软件界面的右端可以显示在线用户列表,分别显示的是用户名,主机名,ip地址.软件左边那大块是聊天内容显示界面,这里局域网相当于qq中的qq群,即群 ...
- Nginx 常见报错
Nginx 常见报错 启动报错:[emerg]: bind() to 0.0.0.0:80 failed (98: Address already in use) 原因:这个是nginx重启时经常遇到 ...
- 非root权限的linux用法添加工作路径
修改~目录的bashrc文件: 1.cd 到~目录. 2.ls -a ,bashrc文件是隐藏的. 3.vim .bashrc;export PATH=$PAHT:要添加的工作路径. 4.source ...