声明:
本文借鉴鸿洋大神博客:
http://blog.csdn.net/lmj623565791/article/details/24529807
首先来看下效果图:
首先来分析下这个控件的组成:
1.音量图标
2.弧形的线
音量图标可以之间使用canvas.drawBitmap方法直接绘制上去
弧线绘制也可以使用canvas.drawArc来绘制,这里我们要对画笔进行一些是设置,在下面会详细讲解:
1.首先来重写一些所必要的方法
package wkk.dome4;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Administrator on 2016/5/15.
*/
public class RoundView extends View {
//画笔
private Paint paint;
//画笔的粗细,即圆环的宽度
private int thickness = 13;
//音量的总个数
private int size = 12;
//音量的大小
private int istrue = 10;
//音量间的间距
private int distance = 15;
//1.构造方法,一般用来初始化相关变量,以及得到所自定义的属性
public RoundView(Context context, AttributeSet attrs) {
super(context, attrs);
paint=new Paint();
}
//2.对控件的大小进行设置
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
//3.主要用来绘图的方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
//4.处理与用户的交互
@Override
public boolean onTouchEvent(MotionEvent event) {
return super.onTouchEvent(event);
}
}
一般来说重写的有以上几个方法,但是并非所有的方法都要重写,根据自己的需要去重写
2.重写onMeasure
首先我们来看一下啊没有重写时的效果
//3.主要用来绘图的方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.BLUE);
//绘制矩形,参数分别为left,top,rightt,tottom,paint
canvas.drawRect(0,0,getWidth(),getHeight(),paint);
}
<wkk.dome1.RoundView
android:layout_width="200dp"
android:layout_height="200dp" />
此时的效果是这样的
看起来很正常,我们来将宽和高改成wrap_content之后来看看效果:
好吧,这并不是我想要的效果,想要不是这样的效果我们来重写onMeasure方法以控制控件的大小:
//2.对控件的大小进行设置
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//得到控件的宽高以及模式
int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int widthMode=MeasureSpec.getMode(widthMeasureSpec);
int heightSize=MeasureSpec.getSize(heightMeasureSpec);
int heightMode=MeasureSpec.getMode(heightMeasureSpec);
int width=0;
int height=0;
//widthMode 即是宽度的模式 即用来判断宽度是wrap_content还是match_parent
//MeasureSpec.EXACTLY代表的是match_parent以及具体的数值例如200dp
if(widthMode!= MeasureSpec.EXACTLY&&heightMode!= MeasureSpec.EXACTLY){
//此方法通知View修改控件宽高
setMeasuredDimension(width, height);
} else {
//如果宽高中有一个是定义的具体数值,我们去最小值
width = Math.min(widthSize, heightSize);
setMeasuredDimension(width, width);
}
}
3.重写最重要的onDraw方法
//3.主要用来绘图的方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//对画笔进行设置
//防抖动
paint.setDither(true);
//防锯齿
paint.setAntiAlias(true);
//设置画笔的宽度
paint.setStrokeWidth(thickness);
//画笔颜色
paint.setColor(Color.WHITE);
//设置样式为空心
paint.setStyle(Paint.Style.STROKE);
//定义线段形状-设置了这个之后 线段的开头和结尾都会变得有弧度
paint.setStrokeCap(Paint.Cap.ROUND);
//得到圆心的x轴坐标
int a = getWidth() / 2;
//因为绘制的圆环是以画笔的宽度来决定内院和外圆的距离的所以要/2
int b = a - thickness / 2;
//参数为矩形的四个点的坐标
RectF f = new RectF(a - b, a - b, a + b, a + b);
//绘制圆弧 参数为 矩形 起始位置 结束距离 画笔
canvas.drawArc(f, -180, 10, false, paint);
}
看下效果:
现在线段就有了,我们只需要通过循环去绘制每一个音量就行了
//3.主要用来绘图的方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//对画笔进行设置
//防抖动
paint.setDither(true);
//防锯齿
paint.setAntiAlias(true);
//设置画笔的宽度
paint.setStrokeWidth(thickness);
//画笔颜色
paint.setColor(Color.WHITE);
//设置样式为空心
paint.setStyle(Paint.Style.STROKE);
//定义线段形状-设置了这个之后 线段的开头和结尾都会变得有弧度
paint.setStrokeCap(Paint.Cap.ROUND);
//得到圆心的x轴坐标
int a = getWidth() / 2;
//因为绘制的圆环是以画笔的宽度来决定内院和外圆的距离的所以要/2
int b = a - thickness / 2;
//参数为矩形的四个点的坐标
RectF f = new RectF(a - b, a - b, a + b, a + b);
//总弧度
int z = 250;
//每一个音量所占据的弧度
int one = (z - ((size - 1) * distance)) / size;
//圆弧的起始位置
int s = -180 - (z - 180) / 2;
//绘制选中
for (int i = 1; i <= istrue; i++) {
//绘制圆弧 参数为 矩形 起始位置 结束距离 画笔
canvas.drawArc(f, s, one, false, paint);
s = s + one + distance;
}
paint.setColor(0xaa25221C);
//绘制未选中
for (int i = 1; i <= size - istrue; i++) {
canvas.drawArc(f, s, one, false, paint);
s = s + one + distance;
}
}
看下效果:
怎么样,基本上和我们所需要的效果相差无几了,接下来绘制音量图标,这个就简单了:
在onDraw方法中继续添加代码:
//绘制图标
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_a);
int c = (getWidth() - bitmap.getWidth()) / 2;
//参数为所需要绘制的bitmap 左边位置 顶部位置 画笔
canvas.drawBitmap(bitmap, c, c, paint);
效果如图:
4.重写:onTouchEvent
处理响应用户点击,并提供向外部提供方法
//4.处理与用户的交互
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
float x = event.getX();
if (x > getRight() / 2) {
jian();
} else {
jia();
}
}
return true;
}
//加
public void jia() {
if (istrue < size) {
istrue += 1;
invalidate();
}
}
//减
public void jian() {
if (istrue > 0) {
istrue -= 1;
invalidate();
}
}
在这里我因为方便就没有去将相关属性写成自定义除属性,当然有需要的可以自己将其提取出来
源码下载地址:
http://download.csdn.net/detail/w18756901575/9520985