以创建一个环状饼图为例讲解安卓中自定义View的用法。
自定义属性值
values文件夹中新建一个.xml文件,用于存储属性值。
格式:attrs.xml
根标签下可以定义多个变量;
中定义属性值,format
为属性类型;
其他的属性类型:
usage |
---|
获取自定义属性
TimeRingView.java
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,R.styleable.RoundRateView,0);
int n = a.getIndexCount(); //自定义属性的个数
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i); //获取逐条属性
switch (attr) {
case R.styleable.RoundRateView_RateColor1:
RateColor1 = a.getColor(attr,Color.parseColor("#fac62d"));
break;
case R.styleable.RoundRateView_RateColor3:
RateColor2 = a.getColor(attr,Color.parseColor("#65cff6"));
break;
case R.styleable.RoundRateView_RateColor2:
RateColor3 = a.getColor(attr,Color.parseColor("#fe9a9c"));
break;
case R.styleable.RoundRateView_RateColor4:
RateColor4 = a.getColor(attr,Color.parseColor("#a286da"));
break;
case R.styleable.RoundRateView_circleWidth:
mCircleWidth = a.getDimensionPixelSize(attr,dp2px(context,20));
break;
case R.styleable.RoundRateView_radius:
mRadius = a.getDimensionPixelSize(attr,20));
break;
}
}
a.recycle();</code></pre>
这一步主要是使得可以在java文件中使用xml文件中定义的属性。
RateColor1/RateColor2等变量都是需要在类中先申明的,这里就省去了。
重写onMeasure方法 设置控件在布局中的大小
TimeRingView.java
@Override
protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) {
// 设置宽度
int specMode = MeasureSpec.getMode(widthMeasureSpec); //获取控件中layout_width设定大小模式(有wrap_content,match_parent和具体数值)
int specSize = MeasureSpec.getSize(widthMeasureSpec); //获取系统设定的控件宽度
int mHeight = 0;
int mWidth = 0;
if (specMode == MeasureSpec.EXACTLY)//当控件大小设定为match_parent或者是具体值时
{
mWidth = specSize;
} else{
if (specMode == MeasureSpec.AT_MOST)//控件layout_width设定为wrap_content,将控件宽度设置为圆环半径的两倍
{
mWidth = (int) (mRadius*2);
}
}
// 设置高度
specMode = MeasureSpec.getMode(heightMeasureSpec);
specSize = MeasureSpec.getSize(heightMeasureSpec);
if (specMode == MeasureSpec.EXACTLY)// match_parent,accurate
{
mHeight = specSize;
} else{
if (specMode == MeasureSpec.AT_MOST)//控件layou_hight设定为wrap_content,将控件高度设置为圆环半径的两倍
{
mHeight = (int) (mRadius*2);
}
}
setMeasuredDimension(mWidth+10,mHeight+10);//最后应用到项目的时候发现圆饼有些超出控件定义的大小,所以将控件总大小稍微加大一点
}</code></pre>
初始化画笔
TimeRingView.java
void initPaint(){
mPaint = new Paint();
mPaint.setAntiAlias(true); //抗锯齿
mPaint.setStyle(Paint.Style.STROKE); //描边style
}
重写onDraw方法 绘制自定义控件
TimeRingView.java
protected void onDraw(Canvas canvas) {
mPaint.setStrokeWidth(mCircleWidth); //画笔宽
//arc 1
mRectF = new RectF(mCircleWidth/2,mCircleWidth/2,mRadius*2 - mCircleWidth/2,mRadius*2-mCircleWidth/2); //(left,top,right,bottom)
float startAngle = -90; //12点方向
float Sweep1 = 150; //弧度
mPaint.setColor((int) RateColor1); //画笔颜色
canvas.drawArc(mRectF,startAngle,Sweep1,false,mPaint);
//arc 2
startAngle += Sweep1;
float Sweep2 = 50;
mPaint.setColor((int) RateColor3);
canvas.drawArc(mRectF,Sweep2,mPaint);
//arc 3
startAngle += Sweep2;
float Sweep3 = 95;
mPaint.setColor((int) RateColor2);
canvas.drawArc(mRectF,Sweep3,mPaint);
//arc 4
startAngle += Sweep3;
float Sweep4 = 65;
mPaint.setColor((int) RateColor4);
canvas.drawArc(mRectF,Sweep4,mPaint);
添加到布局文件
time_ring_layout.xml
其中xmlns:***(app)="http://schemas.android.com/apk/res-auto"
为自定义命名空间
以上就完成了一个数据写死了的环状饼图。想要更改数据只需要增加一个相应方法即可。
P.S.
Utils.java
public static int dp2px(Context context,float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}