构造器开始->onAttachedToWindow()->
onMeasure(int, int)->
onSizeChanged(int, int, int, int)->
onLayout(boolean, int, int, int, int)->
onDraw(android.graphics.Canvas)->
onDetachedFromWindow()
Measure the view and its content to determine the measured width and the measured height. This method is invoked bymeasure(int, int)
and should be overriden by subclasses to provide accurate and efficient measurement of their contents.
用于测量view,用于决定测量的with与测量的height。这个方法由measure()调用,而且这个方法由继承view的子类复写,以便于提供有效而且精确的测量值。
所以自定义view的时候应该要复写onmeasure()的方法,测量view的宽与高,然后通过setMeasuredDimension(measuredWidth, measuredHeight);的方法给出一个用于测量的精确有效的值。这样用于测量精确有效的值应该就是你的view 中getWidth() getHeight()返回的测量值。为什么要这样子做,比如说在我们xml写布局的时候,我们喜欢用mach_parent 与wrap_parent来限制宽与高,mach_parent:与父试图一样大小尺度,wrap_parent:给与足够显示大小的尺寸,还有就是给与一个精确的尺寸。
举个例子:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); int withsize=MeasureSpec.getSize(widthMeasureSpec); int heighsize=MeasureSpec.getSize(heightMeasureSpec); Log.i("-------------", withsize+"/"+heighsize); }并且打印
Log.i("getwith", getWidth()+"");
Log.i("getheigh", getHeight()+"");
xml里代码如下:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:circle="http://schemas.android.com/apk/res/com.example.cirleprogress" android:layout_width="200dp" android:layout_height="200dp" > <com.example.cirleprogress.CircleProgressView android:layout_width="50dp" android:layout_height="50dp" circle:backgroundcolor="#00bcd4" /> </RelativeLayout>
___________ 50/200
___________ 50/50
___________ 50/200
___________ 50/50
发现打印了四次,这个待会再说,最后打印出来的结果是50/50,与我们布局里面设置的大小是一样的,这么说来,获取的数据是view的宽与高,而getheigh与getwith 打印出来都是50
我们设置xml:
<com.example.cirleprogress.CircleProgressView android:layout_width="wrap_content" android:layout_height="wrap_content" circle:backgroundcolor="#00bcd4" />发现打印出来的是200/200,同理如果设置的是match_parent打印出来的也是200/200,打印getheigh与getwith 都是200.
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); int withsize=MeasureSpec.getSize(widthMeasureSpec); int heighsize=MeasureSpec.getSize(heightMeasureSpec); Log.i("-------------", withsize+"/"+heighsize); setMeasuredDimension(20, 20);}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); int withsize = MeasureSpec.getSize(widthMeasureSpec); int heighsize = MeasureSpec.getSize(heightMeasureSpec); int withmode = MeasureSpec.getMode(widthMeasureSpec); int heightmode = MeasureSpec.getMode(heightMeasureSpec); if (withmode == MeasureSpec.AT_MOST) { withsize = 200; } if (heightmode == MeasureSpec.AT_MOST) { heighsize = 200; } setMeasuredDimension(withsize, heighsize);<strong> }
<strong><span style="font-size:18px;">这里注意这个measursSpec. A MeasureSpec encapsulates the layout requirements passed from parent to child 意思就是这个东西囊括了一个layout的所有东西,通过parent传递给child。所有东西是指模式,与尺寸。模式就是指是wrap_conten,还是match_conten,还是精确值,尺寸就是宽与高的具体数据。 总共有三个模式: AT_MOST chile有多大就有多大,但不超父布局尺寸,是指 wrap_conten Measure specification mode: The child can be as large as it wants up to the specified size. EXACTLY 精确尺寸模式,精确尺寸或者match_parent Measure specification mode: The parent has determined an exact size for the child. UNSPECIFIED 没有指定尺寸 Measure specification mode: The parent has not imposed any constraint on the child.</span> </strong> <span style="font-size:18px;"><strong>最后测试发现得到:如果Vie设置的宽/高 是wrap_conten 或者是match_parent onmeasure(),返回的宽/高一定是Viewgroup的宽/高,如果viewgroup的宽/高 是wrap_conten 或者是match_parent,那么返回的是上一级Viewgroup 的宽/高,以此类推。如果Vie设置的宽/高 是小于viewgroup的宽/高,那么返回的是view设置的宽/高,如果大于parent viewgroup的宽/高 那么返回的是Viewgroup 的宽/高,以此类推最后到达的一级是屏幕的宽/高。 用于控制view 的children的位置与大小</strong></span> Called from layout when this view should assign a size and position to each of its children protected void onLayout(boolean changed, int left, int top, int right, int bottom) changed - This is a new size or position for this view left - Left position, relative to parent top - Top position, relative to parent right - Right position, relative to parent bottom - Bottom position, relative to parent
接下来说一下为什么onmeasure()会调用多次,答案就是下面这句话: