转载请标明出处: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 (四) 视频音量调控的更多相关文章

  1. Android 自定义View (四) 视频音量调控

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24529807 今天没事逛eoe,看见有人求助要做一个下面的效果,我看下面一哥们说 ...

  2. Android 自己定义View学习(2)

    上一篇学习了基本使用方法,今天学一下略微复杂一点的.先看一下效果图 为了完毕上面的效果还是要用到上一期开头的四步 1,属性应该要有颜色,要有速度 <?xml version="1.0& ...

  3. Android 自己定义View (二) 进阶

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/24300125 继续自己定义View之旅.前面已经介绍过一个自己定义View的基础 ...

  4. Android 自己定义View须要重写ondraw()等方法

    Android  自己定义View须要重写ondraw()等方法.这篇博客给大家说说自己定义View的写法,须要我们继承View,然后重写一些 方法,方法多多,看你须要什么方法 首先写一个自己定义的V ...

  5. 【Android自己定义View实战】之自己定义超简单SearchView搜索框

    [Android自己定义View实战]之自己定义超简单SearchView搜索框 这篇文章是对之前文章的翻新,至于为什么我要又一次改动这篇文章?原因例如以下 1.有人举报我抄袭,原文链接:http:/ ...

  6. Android自己定义view之measure、layout、draw三大流程

    自己定义view之measure.layout.draw三大流程 一个view要显示出来.须要经过測量.布局和绘制这三个过程,本章就这三个流程具体探讨一下.View的三大流程具体分析起来比較复杂,本文 ...

  7. Android自己定义View的实现方法

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/17357967 不知不觉中,带你一步步深入了解View系列的文章已经写到第四篇了.回 ...

  8. Android自己定义View基础篇(三)之SwitchButton开关

    自己定义View基础篇(二) 自己定义View基础篇(一) 自己定义View原理 我在解说之前,先来看看效果图,有图有真相:(转换gif图片效果太差) 那来看看真实图片: 假设你要更改样式,请改动例如 ...

  9. 手把手带你画一个 时尚仪表盘 Android 自己定义View

    拿到美工效果图.咱们程序猿就得画得一模一样. 为了不被老板喷,仅仅能多练啊. 听说你认为前面几篇都so easy,那今天就带你做个相对照较复杂的. 转载请注明出处:http://blog.csdn.n ...

随机推荐

  1. [转]Android网格视图(GridView)

    GridView的一些属性: 1.android:numColumns=”auto_fit”   //GridView的列数设置为自动,也可以设置成2.3.4…… 2.android:columnWi ...

  2. ES6系列汇总

    汇 总 第一节:什么是ES6?新手该如何理解 第二节:ES6新增了let关键字,干嘛用的? 第三节:ES6中另一个不得不说的关键字const 第四节:教你如何快速让浏览器兼容ES6特性 第五节:一个令 ...

  3. Tasker, Android系统增强神器

    Tasker是一个让系统根据用户定制的”配置文件”(Profiles),在特定的”背景”下(Contexts),执行指定”任务”(Tasks)的软件, 除此之外,它还提供”可供点击”的(Clickab ...

  4. 让mbox支持up效果

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  5. 为什么少有人在Windows电脑上安OS X?

    问:为什么许多人在Mac上安装Windows,却很少有人在PC上安装OS X呢?(注:通常,我们定义运行Windows的电脑为PC,而Mac的操作系统则为OS X) 答:iPhone的真正流行让更多的 ...

  6. Android 集成新浪微博分享及授权 (上)

    2014-05-05 20:16 10663人阅读 评论(8) 收藏 举报  分类: android(33)  版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] 第一部分  ...

  7. unity3d-地图制作之暗光

    最近看了暗黑破坏神3的视频,看到游戏里面的场景画面,颇有感触. 画面可谓做的极好的,虽然我审美观不是那么滴好,但是这游戏就让我看的赏心悦目,就让我好想来撸那么一把. 看完暗黑视频后,我就开始研究里面的 ...

  8. Thymeleaf th:action

    th:attr 任何属性值 <form action="subscribe.html" th:attr="action=@{/subscribe}"> ...

  9. 从头開始写项目Makefile(十):make内嵌函数及make命令显示

    [版权声明:转载请保留出处:blog.csdn.net/gentleliu.Mail:shallnew at 163 dot com]     这一节我们讲一下make的函数,在之前的章节已经讲到了几 ...

  10. @ERR Unsupported CONFIG parameter: notify-keyspace-events

    Caused by: redis.clients.jedis.exceptions.JedisDataException: ERR Unsupported CONFIG parameter: noti ...