自定义View(10)*onSizeChanged,onMeasure,onDraw的注意事项及正确写法
1,onSizeChanged
触发:
当view的第一次分配大小或以后大小改变时的产生的事件。
工作:
计算绘制内容的位置,面积等相关值。避免每次在onDraw中计算了。
注意:
计算时不要忘记padding。这是个责任。
示范:
1 // Account for padding 2 float xpad = (float)(getPaddingLeft() + getPaddingRight()); 3 float ypad = (float)(getPaddingTop() + getPaddingBottom()); 4 5 // Account for the label 6 if (mShowText) xpad += mTextWidth; 7 8 float ww = (float)w - xpad; 9 float hh = (float)h - ypad; 10 11 // Figure out how big we can make the pie. 12 float diameter = Math.min(ww, hh);
2,onMeasure
触发:
当父控件布局时,要测量子控件的大小,当调用子控件measure要求强制测量或实在无法确定其大小时(先是上次MeasureSpec值不同,再是缓存中找不到对应值),触发子控件onMeasure,子控件在其中确定和部分绘制内容的大小。
见: http://www.cnblogs.com/sjjg/p/5193909.html
工作:
解析传来的参数,设置各绘制内容大小。
注意:
a,传来的参数是长宽的压缩值,要解析后只是最大或建议的大小,可以在onMeasure中指定最大范围内的值。
b,并且必需调用 setMeasuredDimension方法。
c,不要忘记padding。这是个责任。
示范:
1 @Override 2 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 3 4 // Try for a width based on our minimum 5 //最小宽度 6 int w = getPaddingLeft() + getPaddingRight() + getSuggestedMinimumWidth(); 7 8 //如果给出的建议是0,可以手动设置一个期望值。单位是像素。同时这步一定要在resolveSizeAndState前, 9 // 因为它可能大于widthMeasureSpec的最大值。 10 if (w == 0) w = 56; 11 12 //计算最佳值,在其中解析了 widthMeasureSpec 13 w = resolveSizeAndState(w, widthMeasureSpec, 0); 14 15 // Whatever the width ends up being, ask for a height that would let the pie 16 // get as big as it can 17 //最小高度 18 int h = getSuggestedMinimumHeight() + getPaddingBottom() + getPaddingTop(); 19 20 //如果给出的建议是0,可以手动设置一个期望值。单位是像素。同时这步一定要在resolveSizeAndState前, 21 // 因为它可能大于heightMeasureSpec的最大值。 22 if (h == 0) h = 56; 23 24 //计算最佳值,在其中解析了 heightMeasureSpec 25 h = resolveSizeAndState(h, heightMeasureSpec, 0); 26 27 28 //将量算的结果保存到View的成员变量mMeasuredWidth 和mMeasuredHeight中。 29 setMeasuredDimension(w, h); 30 31 // 量算完成之后,View的父控件就可以通过调用 32 // getMeasuredWidth、getMeasuredState、getMeasuredWidthAndState 33 // 这三个方法获取View的量算结果。 34 35 }
3,onDraw
触发:
绘制事件,绝大多数时是由于调用invalidate()触发。
工作:
绘制点,线,图形,路径,图片等。
注意:
这个方法调用频度非常高,不要在里面申请内存,不要绘制时间过长,不要重复计算等。少调用invalidate()。
示范:
1 protected void onDraw(Canvas canvas) { 2 super.onDraw(canvas); 3 4 // Draw the shadow 5 canvas.drawOval( 6 mShadowBounds, 7 mShadowPaint 8 ); 9 10 // Draw the label text 11 canvas.drawText(mData.get(mCurrentItem).mLabel, mTextX, mTextY, mTextPaint); 12 13 // Draw the pie slices 14 for (int i = 0; i < mData.size(); ++i) { 15 Item it = mData.get(i); 16 mPiePaint.setShader(it.mShader); 17 canvas.drawArc(mBounds, 18 360 - it.mEndAngle, 19 it.mEndAngle - it.mStartAngle, 20 true, mPiePaint); 21 } 22 23 // Draw the pointer 24 canvas.drawLine(mTextX, mPointerY, mPointerX, mPointerY, mTextPaint); 25 canvas.drawCircle(mPointerX, mPointerY, mPointerSize, mTextPaint); 26 }