Android 自己定义View (四) 视频音量调控
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24529807
今天没事逛eoe,看见有人求助要做一个以下的效果,我看以下一哥们说要用12张图片,这尼玛逆天的麻烦,细致看了一下感觉自己定义控件木有问题,就花点时间写了一个。
好了,进入正题,继续我们的自己定义View四部曲。
1、先分许须要的属性,两个小块的颜色、一张中间的图片、间隙大小、一个多少个块块。分析完成,開始写attr.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"></attr> <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、在构造中获取这些属性:
/**
* 第一圈的颜色
*/
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; public CustomVolumControlBar(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
} public CustomVolumControlBar(Context context)
{
this(context, null);
} /**
* 必要的初始化,获得一些自己定义的值
*
* @param context
* @param attrs
* @param defStyle
*/
public CustomVolumControlBar(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomVolumControlBar, defStyle, 0);
int n = a.getIndexCount(); for (int i = 0; i < n; i++)
{
int attr = a.getIndex(i);
switch (attr)
{
case R.styleable.CustomVolumControlBar_firstColor:
mFirstColor = a.getColor(attr, Color.GREEN);
break;
case R.styleable.CustomVolumControlBar_secondColor:
mSecondColor = a.getColor(attr, Color.CYAN);
break;
case R.styleable.CustomVolumControlBar_bg:
mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(attr, 0));
break;
case R.styleable.CustomVolumControlBar_circleWidth:
mCircleWidth = a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_PX, 20, getResources().getDisplayMetrics()));
break;
case R.styleable.CustomVolumControlBar_dotCount:
mCount = a.getInt(attr, 20);// 默认20
break;
case R.styleable.CustomVolumControlBar_splitSize:
mSplitSize = a.getInt(attr, 20);
break;
}
}
a.recycle();
mPaint = new Paint();
mRect = new Rect();
}
3、重写onDraw
@Override
protected void onDraw(Canvas canvas)
{
mPaint.setAntiAlias(true); // 消除锯齿
mPaint.setStrokeWidth(mCircleWidth); // 设置圆环的宽度
mPaint.setStrokeCap(Paint.Cap.ROUND); // 定义线段断电形状为圆头
mPaint.setAntiAlias(true); // 消除锯齿
mPaint.setStyle(Paint.Style.STROKE); // 设置空心
int centre = getWidth() / 2; // 获取圆心的x坐标
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);
} /**
* 依据參数画出每一个小块
*
* @param canvas
* @param centre
* @param radius
*/
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); // 依据进度画圆弧
}
}
这里须要注意下:
画块:首先依据块数量和间隙计算,每一个块所占的比例。
绘图:当图比較大时,直接使用该环内切正方形大小进行约束,当图片比較小时,在正中心的位置绘制。有些数学运算过程,楼主在草稿上画了一会,不复杂,大家自己画画,我就不贴草稿了。
4、加入触摸监听:
/**
* 当前数量+1
*/
public void up()
{
mCurrentCount++;
postInvalidate();
} /**
* 当前数量-1
*/
public void down()
{
mCurrentCount--;
postInvalidate();
} private int xDown, xUp; @Override
public boolean onTouchEvent(MotionEvent event)
{ switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
xDown = (int) event.getY();
break; case MotionEvent.ACTION_UP:
xUp = (int) event.getY();
if (xUp > xDown)// 下滑
{
down();
} else
{
up();
}
break;
} return true;
}
触摸监听也得非常easy哈,基本能实现,大家也能够加个最小距离加速度什么的,都行。
最后,效果图:
可惜楼主尼玛是找不到那个音量的图,不要叫我去抠图哈,就随便拿了几张图片来试试。
嘿嘿,留个言,顶一个哈~
Android 自己定义View (四) 视频音量调控的更多相关文章
- Android 自定义View (四) 视频音量调控
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24529807 今天没事逛eoe,看见有人求助要做一个下面的效果,我看下面一哥们说 ...
- Android 自己定义View学习(2)
上一篇学习了基本使用方法,今天学一下略微复杂一点的.先看一下效果图 为了完毕上面的效果还是要用到上一期开头的四步 1,属性应该要有颜色,要有速度 <?xml version="1.0& ...
- Android 自己定义View (二) 进阶
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自己定义View之旅.前面已经介绍过一个自己定义View的基础 ...
- Android 自己定义View须要重写ondraw()等方法
Android 自己定义View须要重写ondraw()等方法.这篇博客给大家说说自己定义View的写法,须要我们继承View,然后重写一些 方法,方法多多,看你须要什么方法 首先写一个自己定义的V ...
- 【Android自己定义View实战】之自己定义超简单SearchView搜索框
[Android自己定义View实战]之自己定义超简单SearchView搜索框 这篇文章是对之前文章的翻新,至于为什么我要又一次改动这篇文章?原因例如以下 1.有人举报我抄袭,原文链接:http:/ ...
- Android自己定义view之measure、layout、draw三大流程
自己定义view之measure.layout.draw三大流程 一个view要显示出来.须要经过測量.布局和绘制这三个过程,本章就这三个流程具体探讨一下.View的三大流程具体分析起来比較复杂,本文 ...
- Android自己定义View的实现方法
转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了.回 ...
- Android自己定义View基础篇(三)之SwitchButton开关
自己定义View基础篇(二) 自己定义View基础篇(一) 自己定义View原理 我在解说之前,先来看看效果图,有图有真相:(转换gif图片效果太差) 那来看看真实图片: 假设你要更改样式,请改动例如 ...
- 手把手带你画一个 时尚仪表盘 Android 自己定义View
拿到美工效果图.咱们程序猿就得画得一模一样. 为了不被老板喷,仅仅能多练啊. 听说你认为前面几篇都so easy,那今天就带你做个相对照较复杂的. 转载请注明出处:http://blog.csdn.n ...
随机推荐
- 无线遥控器方案 Si4010/Si4012
Si4010包含一个嵌入式兼容8051微控制器(MCU),内具4 kB的RAM.8 kB的一次性编程(OTP)非易失性内存.一个128位EEPROM以及用于函数库(library)功能的12 kB R ...
- 程序猿怎样变身IT讲师
我以前写过一篇文章,"一张图道尽程序猿的出路",里面有一张图: 这张图随着"一张图道尽程序猿的出路"这篇文章,以前被伯乐在线.docin(豆丁网).IT面试.J ...
- JSON还原为结构体
JSON还原为结构体 1)JSON字符串还原为结构体: 2)访问结构体的字段值: 本例运行效果图: uses SynCommons; const // JSON字符串 JSON1 = '{' + #1 ...
- Multiline ComboBox
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- jenkins中“Poll SCM”和“Build periodically”的区别
Poll SCM:定时检查源码变更(根据SCM软件的版本号),如果有更新就checkout最新code下来,然后执行构建动作.我的配置如下: */5 * * * * (每5分钟检查一次源码变化) B ...
- ZooKeeper目录
1. Zookeeper常用命令 (转) 2. ZooKeeper安装和配置(转) 3. Spark集群基于Zookeeper的HA搭建部署笔记(转)
- Jenkins自动部署到(远程)tomcat服务器
Jenkins的流程: 1.从版本控制中获取代码 ->2. 使用maven编译生成相应的包(jar,war) ->3. 部署到指定的地点. 其中2.主要是解决依赖的问题,或许你需要先mvn ...
- 视频运行库AVICAP32.DLL说明收藏
视频运行库AVICAP32.DLL说明收藏2008-09-28 09:04 // ----------------------------------------------------------- ...
- 1 cocos2dx源码分析-程序启动与主循环
1 启动 在iOS系统中,由main函数启动默认调用了AppController main.m NSAutoreleasePool * pool = [[NSAutoreleasePool ...
- iOS:shareSDK第三方登录
shareSDK第三方登录跟分享差不多,比较简单,前面已有介绍.这里简单写一下第三方登录吧. 1.首先:我用到了QQ.微信.新浪这三个平台的登录,需要到它们各自的开发者平台注册开发者账号,这是我的QQ ...