这里实现一个饼图自定义控件View :
第一步:
在values中创建attrs.xml 属性文件如下;
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomView">
<attr name="start_angle" format="integer"/>
<attr name="move_angle" format="float"/>
</declare-styleable>
</resources>
第二步:
继承View控件实现之定义控件:
public class CustomView extends View {
private String TAG="IMListView";
private Paint mPaint;
private RectF oval;
private int start_angle;
private float move_angle;
public CustomView(Context context) {
super(context);
init(context,null);
}
public CustomView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
}
private void init(Context context,AttributeSet attributeSet){
mPaint = new Paint();
mPaint.setAntiAlias(true);
oval=new RectF();
if (attributeSet!=null) {
TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.CustomView);
int indexCount = typedArray.getIndexCount();
for (int i = 0; i < indexCount; i++) {
int index = typedArray.getIndex(i);
if (index==R.styleable.CustomView_start_angle)
{
start_angle = typedArray.getInteger(index, 180);
}
if (index==R.styleable.CustomView_move_angle)
{
move_angle = typedArray.getFloat(index, 135f);
}
}
typedArray.recycle();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int wmode = MeasureSpec.getMode(widthMeasureSpec);
int hmode = MeasureSpec.getMode(heightMeasureSpec);
int wsize = MeasureSpec.getSize(widthMeasureSpec);
int size = MeasureSpec.getSize(heightMeasureSpec);
switch (wmode) {
case MeasureSpec.AT_MOST:
Log.i(TAG, "onMeasure: AT_MOST");
break;
case MeasureSpec.EXACTLY:
Log.i(TAG, "onMeasure: EXACTLY");
break;
case MeasureSpec.UNSPECIFIED:
Log.i(TAG, "onMeasure: UNSPECIFIED");
break;
}
Log.i(TAG, "onMeasure: width:"+wsize+"--height:"+ size);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
Log.i(TAG, "onLayout: "+changed);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.GRAY);
// FILL填充, STROKE描边,FILL_AND_STROKE填充和描边
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
int with = getWidth();
int height = getHeight();
Log.e(TAG, "onDraw---->" + with + "*" + height);
float radius = with / 4;
canvas.drawCircle(with / 2, with / 2, radius, mPaint);
mPaint.setColor(Color.BLUE);
oval.set(with / 2 - radius, with / 2 - radius, with / 2
+ radius, with / 2 + radius);//用于定义的圆弧的形状和大小的界限
canvas.drawArc(oval, start_angle, move_angle, true, mPaint); //根据进度画圆弧
}
}
说明:
onMeasure是测绘控件吃存并且设置宽度和高度属性的方法,检测中有三种模式;
(1) UPSPECIFIED :父容器对于子容器没有任何限制,子容器想要多大就多大.
(2) EXACTLY父容器已经为子容器设置了尺寸,子容器应当服从这些边界,不论子容器想要多大的空间.
(3) AT_MOST子容器可以是声明大小内的任意大小.
onLayout是布局方法,主要用户ViewGroup布局子控件的方法。
onDraw是绘制显示内容的方法,在View他是空方法,在其他控件中有具体的逻辑。
init方法是来获取上面声明自定义属性的值。
第三步:
调用布局自定义控件:
<com.chenxing.searchjob.sdk.view.CustomView
app:start_angle="180"
app:move_angle="90"
android:layout_width="100dp"
android:layout_height="100dp" />
其中app:要在布局中声明例如:
xmlns:app="http://schemas.android.com/apk/res-auto"
也可以直接在控件布局中声明:
<com.chenxing.searchjob.sdk.view.CustomView
xmlns:app="http://schemas.android.com/apk/res-auto"
app:start_angle="180"
app:move_angle="90"
android:layout_width="100dp"
android:layout_height="100dp" />