现在我们来举例讲解自定义的第一种,继承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
最近搞了个Android技术分享的公众号,欢迎关注投稿。 