转自:鸿洋博客,正在学习,非常感谢!
今天学习的是一个音量调节的demo:
最终效果图如下:
1.基本的属性设置:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="firstColor" format="color" />
<attr name="secondColor" format="color" />
<attr name="cicleWidth" format="dimension" />
<attr name="bg" format="reference" />
<attr name="docount" format="integer" />
<attr name="splitSize" format="dimension" />
<declare-styleable name="CustomeView4">
<attr name="firstColor" />
<attr name="secondColor" />
<attr name="cicleWidth" />
<attr name="bg" />
<attr name="docount" />
<attr name="splitSize" />
</declare-styleable>
</resources>
2.自定义view:
先初始化我们自己设置的属性:
TypedArray a=context.getTheme().obtainStyledAttributes(attrs,R.styleable.CustomeView4,defStyleAttr,0);
int n=a.getIndexCount();
for (int i=0;i<n;i++){
int attr=a.getIndex(i);
switch (attr){
case R.styleable.CustomeView4_firstColor:
firstColor=a.getColor(attr,Color.RED);
break;
case R.styleable.CustomeView4_secondColor:
secondColor=a.getColor(attr,Color.BLUE);
break;
case R.styleable.CustomeView4_cicleWidth:
cicleWidth=a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,10,getResources().getDisplayMetrics()));
break;
case R.styleable.CustomeView4_docount:
doCount=a.getInt(attr,20);//绘制20个
break;
case R.styleable.CustomeView4_splitSize:
splitSize=a.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,10,getResources().getDisplayMetrics()));
break;
case R.styleable.CustomeView4_bg:
bg= BitmapFactory.decodeResource(getResources(),a.getResourceId(attr,0));
break;
}
}
a.recycle();
现在开始绘制,首先我们可以看出内部是一个圆包裹一个图片,所以整个view的基本区域还是一个圆:
mPaint.setColor(firstColor);
mPaint.setStrokeWidth(cicleWidth);
mPaint.setAntiAlias(true);
int center=getWidth()/2;//圆心位置
int radius=center-cicleWidth/2;
canvas.drawCircle(center,center,radius,mPaint);
绘制出一个圆:
这个是基本区域,现在我们再绘制一个中心图片,就是音量图标:
rect.left=center-bg.getWidth()/2;
rect.right=center+bg.getWidth()/2;
rect.top=center-bg.getHeight()/2;
rect.bottom=center+bg.getHeight()/2;
canvas.drawBitmap(bg,null,rect,mPaint);
结果如下:
现在绘制音量大小:
我们首先要的是一个圆环:
a.只要设置绘制的style是STROKE就可以变成空心的
然后设置中间的间隙,注意开始的时候我用的是绘制圆,但是后期要是一段段的隔开就要变成圆弧,根据数目绘制一定的圆弧。
//绘制小块块
private void drawSpan(Canvas canvas, int radius, int center) {
//根据需要绘制的块块数目来计算间隙,以及在每一个小块块的长,这里是按照一个圆就是一个“单位1”
float itemSize=(360-doCount*splitSize)/doCount;//需要绘制的个数
rectF.left=center-radius;
rectF.right=center+radius;
rectF.top=center-radius;
rectF.bottom=center+radius;
//设置圆环的颜色
mPaint.setColor(firstColor);
for(int i=0;i<doCount;i++){
canvas.drawArc(rectF,i*(splitSize+itemSize),itemSize,false,mPaint);
}
}
这个时候我们发现我们的小块块并不是圆头的,这是因为开始的时候没有给画笔设置这个属性
mPaint.setStrokeCap(Paint.Cap.ROUND);
注意每一个小块块的大小和数据以及要绘制的总数要合理分配,否则就会挤在一起:
最终样式:
这里我们要绘制中心图片,所以还要考虑的问题就是图片的大小,如果图片太大就绘制成为最大的内切正方形否则就绘制在中心位置,所以在这里我们需要设置内切正方形也就是中间图片的绘制区域,这里的图片大还是不大取决于我们的最大内切正方形小于这个值的都设置在中心位置:
int r=radius-cicleWidth/2;//内切正方形的圆
rect.left= (int) (r- Math.sqrt(2)/2*r+cicleWidth);
rect.right= (int) (rect.left+Math.sqrt(2)*r);
rect.top=(int) (r- Math.sqrt(2)/2*r+cicleWidth);
rect.bottom=(int) (rect.left+Math.sqrt(2)*r);
//如果图片太小绘制在中间
if(bg.getWidth()<Math.sqrt(2)*r){
rect.left=r-bg.getWidth()/2+cicleWidth;
rect.right= rect.left+bg.getWidth();
rect.top=r-bg.getHeight()/2+cicleWidth;
rect.bottom=rect.top+bg.getHeight();
}
canvas.drawBitmap(bg,null,rect,mPaint);
最终效果
笔记:
//定义线段断电形状为圆头
mPaint.setStrokeCap(Paint.Cap.ROUND);