现在我们来举例讲解自定义的第一种,继承view,效果如下图示:
直接看代码:
public class CircleView extends View {
private int width;
private int height;
private Paint mPaint;
private RectF mRect;
//定义两个数组,一个表达大小,一个表示颜色
private int[] itemCount={11,22,33,44,55};
private int[] itemColor={Color.BLUE,Color.GREEN,Color.RED,Color.YELLOW,Color.GRAY};
public CircleView(Context context) {
this(context,null);
}
public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initCanvas(context);
}
private void initCanvas(Context context) {
mPaint=new Paint();
mRect= new RectF();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.FILL);
}
public CircleView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize=MeasureSpec.getSize(widthMeasureSpec);
int widthMode=MeasureSpec.getMode(widthMeasureSpec);
switch (widthMode){
case MeasureSpec.EXACTLY://match_parent and 具体的值
width=widthSize;
break;
case MeasureSpec.AT_MOST://wrap_content;
width=getScreenHeight(getContext())/2;
break;
}
height=width;
setMeasuredDimension(width,height);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mRect.left=getLeft();
mRect.top=getTop();
mRect.right=getRight();
mRect.bottom=getBottom();
float xWidth=mRect.right-mRect.left;
float xHeight=mRect.bottom-mRect.top;
float radis;
if(xWidth>xHeight){
radis=xHeight/2;
}else{
radis=xWidth/2;
}
int total=11+22+33+44+55;
float start = 0.0f;
for (int i = 0; i < 5; i++) {
//draw pie
mPaint.setColor(itemColor[i]);
float sweep = (float) itemCount[i] / total * 360;
canvas.drawArc(mRect,start,sweep,true,mPaint);
start += sweep;
}
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
}
/**
* 获得屏幕宽度
*
* @param context
* @return
*/
public int getScreenHeight(Context context) {
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
return outMetrics.heightPixels;
}
}
可以看到,继承自view的主要重写onMeasure和onDraw方法就可以了,onLayout主要继承viewGroup时重写的较多。
在onMeasure方法中,我们有了个简单的判断,主要是为了防止xml布局中宽,长的属性是wrap_content,此时我们默认的圆的半径是屏幕宽的一半。
setMeasuredDimension(width,height);是一个非常重要的方法,真正设置view的大小就是这个方法最终拍板的。
在onDraw方法中,主要是在绘制我们需要的效果图。对paint和canvas不熟悉的人需要加强这部分的知识,因为最定义view最重要的就是自己的绘制,必须要熟悉这些相关的类。
canvas.drawArc(mRect,start,sweep,true,mPaint);就是这个画扇形的方法最后组成了我们想要的一个圆。
细心的小伙伴也许可以发现,如果我在xml中对该view的位置进行一个简单的设置,比如让其居中,此时的扇形甚至都不会出现,这问题主要是出现在canvas.drawArc(mRect,start,sweep,true,mPaint)的mRect这个参数上,这个区域应该是一个相对区域而不是具体的。所以此时的mRect的参数应该这样写:
mRect.left=0;
mRect.top=0;
mRect.right=mRect.left+width;
mRect.bottom=mRect.top+width;
所以我们需要对paint和canvas的api有足够的了解才能自定义出符合要求的view。
下一篇文章 自定义view(二)继承viewgroup,欢迎大家阅读评论。
最近搞了个Android技术分享的公众号,欢迎关注投稿。