一attr
1.作用
attr用于约束属性的数据类型,xml资源文件中定义各种attr,指定attr的数据类型。
在布局文件中为自定义view的xml属性赋值。
在自定义view的构造函数中,解析xml总定义的属性值,将其放入自定义view对应的成员变量中。
2.
<?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="circleImage" format="reference"/>
<declare-styleable name="CustomView">
<!--<attr name="android:galleryItemBackground">-->
<!--</attr>-->
<attr name="firstColor"/>
<attr name="secondColor"/>
<attr name="circleWidth"/>
<attr name="circleImage"/>
</declare-styleable>
</resources>
每个attr都会在R文件里生成一个Id,获取方式为
TypedArray a=context.getTheme().obtainStyledAttributes(attrs,R.styleable.CustomView,defStyleAttr,0);
二Paint
可以当做画笔
mPaint.setColor(Color.RED);//设置画笔的颜色
mPaint.setTextSize(60);//设置文字大小
mPaint.setStrokeWidth(5);//设置画笔的宽度
mPaint.setAntiAlias(true);//设置抗锯齿功能 true表示抗锯齿 false则表示不需要这功能
三Canvas
可以当做画布
canvas.drawArc() 画圆弧
canvas.drawArc(RectF oval,float startAngle,float sweepAngle,boolean useCenter,Paint paint);
oval:定义圆弧的形状和大小的范围
startAngle:设置圆弧从哪个角度顺时针绘画
sweepAngle:设置圆弧扫过的角度
useCenter:画圆弧是否经过圆形
paint:设置画笔对象的属性
四代码实现
1.attr文件
<?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="circleImage" format="reference"/>
<declare-styleable name="CustomView">
<!--<attr name="android:galleryItemBackground">-->
<!--</attr>-->
<attr name="firstColor"/>
<attr name="secondColor"/>
<attr name="circleWidth"/>
<attr name="circleImage"/>
</declare-styleable>
</resources>
2.自定义类VolumeView
public class VolumeView extends View {
private int mFirstColor;//第一圈颜色
private int mSecondColor;//第二圈颜色
private int mCircleWidth;//圈的宽度
private Bitmap mImage;//中间图片
private Paint mPaint; //绘制文本画笔
private int mcout;//当前为第二颜色的小块数量
public VolumeView(Context context) {
this(context, null);
}
public VolumeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public VolumeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a=context.getTheme().obtainStyledAttributes(attrs,R.styleable.CustomView,defStyleAttr,0);
int n=a.getIndexCount();
for(int i=0;i<n;i++){
int attr=a.getIndex(i);
switch(attr)
{
case R.styleable.CustomView_firstColor:
mFirstColor=a.getColor(attr, Color.GREEN);
break;
case R.styleable.CustomView_secondColor:
mSecondColor=a.getColor(attr, Color.CYAN);
break;
case R.styleable.CustomView_circleWidth:
mCircleWidth=a.getDimensionPixelSize(attr,(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics()));
break;
case R.styleable.CustomView_circleImage:
mImage= BitmapFactory.decodeResource(getResources(),a.getResourceId(attr,0));
break;
}
}
a.recycle();
mPaint=new Paint();
}
//重写ondraw
protected void onDraw(Canvas canvas) {
int centrex=getWidth()/2;//圆心中心
int centrey=getHeight()/2;
float radius=(centrex-mCircleWidth/2)*(float)0.4;//半径
mPaint.setStrokeWidth(mCircleWidth);//设置线宽
mPaint.setAntiAlias(true);//消除锯齿
mPaint.setStyle(Paint.Style.STROKE);//设置为空心
mPaint.setStrokeCap(Paint.Cap.ROUND);//设置为线段形状为圆头
//画小块
//设定一个圆弧的边界矩形
RectF oval=new RectF();
oval.left=centrex-radius;
oval.top=centrey-radius;
oval.right=centrex+radius;
oval.bottom=centrey+radius;
mPaint.setColor(mFirstColor);
for(int i=0;i<12;i++){
canvas.drawArc(oval, (270+30*i)%360, 10, false, mPaint);
}
if(mcout<0)mcout=0;
mcout=mcout%13;
mPaint.setColor(mSecondColor);//设置圆环颜色
for(int k=0;k<mcout;k++){
canvas.drawArc(oval,(270+30*k)%360,10,false,mPaint);
}
// //画中间的图片
RectF oval2=new RectF();//设置矩形边界
oval2.left = (int) (centrex+mImage.getWidth()/2);
oval2.top = (int) (centrey-mImage.getHeight()/2);
oval2.right = (int) (centrex-mImage.getWidth());
oval2.bottom = (int) (centrey+mImage.getHeight()/2);
canvas.drawBitmap(mImage,null,oval2,mPaint);
}
//监听事件
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){
mcout++;
postInvalidate();
}else{
mcout--;
postInvalidate();
}
break;
}
return true;
}
}
3.在布局中引用自定义
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
xmlns:volume="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.volumeui.MainActivity">
<com.example.volumeui.VolumeView
android:layout_width="match_parent"
android:layout_height="match_parent"
volume:circleWidth="15dp"
volume:firstColor="#AFEEEE"
volume:secondColor="#5F9EA0"
volume:circleImage="@drawable/a1"
/>
</android.support.constraint.ConstraintLayout>
4.效果图
作者:陈璟雯
链接:点这里