自定义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 }

 

posted @ 2016-06-06 22:48  f9q  阅读(1012)  评论(0编辑  收藏  举报