<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
RelativeLayout>
ps:这边打开hierarchy viewer一直无法刷新到tree view图,直接用了孙群博客里面的图
public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
...//省略代码
onMeasure();
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
protected void measureChild(View child, int parentWidthMeasureSpec,
int parentHeightMeasureSpec) {
...//省略代码
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
protected void measureChildWithMargins(View child,
int parentWidthMeasureSpec, int widthUsed,
int parentHeightMeasureSpec, int heightUsed) {
...//省略代码
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
1.View的measure()是final的,所以其子类不可以重写该方法。
2.View的measure()里面有调用onMeasure()方法,而且onMeasure()不是空方法,即有实现测量过程。子类若
想用自己的测量方式可以重写该方法。ps:一般都会重写onMeasure()。
3.ViewGroup里面只有measureChild(),measureChildWithMargins(),里面都会调用child.measure()方法。
所以准确的来说,其实ViewGroup的子类如果有重写onMeasure()方法,其实是重写了View的onMeasure()方法。
4.一般ViewGroup都会重写onMeasure(),然后里面一般计算child个数并循环调用child.measure()。
5.ps:发现FrameLayout里面有调用ViewGroup.measureChildWithMargins()和child.measure(),RelativeLayout里面只有child.measure()。LinearLayout里面有调用ViewGroup.meaChildWithMargins()和child.measure()。
ViewRootImpl.doTraversal()->
ViewRootImpl.performTraversals()->
//开始测量
ViewRootImpl.performMeasure()->
PhoneWindow$DecorView执行View.measure()->
PhoneWindow$DecorView.onMeasure()->
PhoneWindow$DecorView执行ViewGroup.measureChildWithMargins()和child.measure()->
LinearLayout执行View.measure()->
LinearLayout.onMeasure()->
LinearLayout执行ViewGroup.measureChildWithMargins()和child.measure()->
FrameLayout执行View.measure()->
FrameLayout.onMeasure()->
FrameLayout执行ViewGroup.measureChildWithMargins()和child.measure()->
RelativeLayout执行View.measure()->
RelativeLayout.onMeasure()->
RelativeLayout执行child.measure()->
TextView执行View.measure()->
TextView.onMeasure()
public void layout(int l, int t, int r, int b) {
...//省略代码
onLayout();
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {}
public final void layout(int l, int t, int r, int b) {
if (!mSuppressLayout && (mTransition == null || !mTransition.isChangingLayout())) {
if (mTransition != null) {
mTransition.layoutChange(this);
}
super.layout(l, t, r, b);
} else {
// record the fact that we noop'd it; request layout when transition finishes
mLayoutCalledWhileSuppressed = true;
}
}
protected abstract void onLayout(boolean changed,
int l, int t, int r, int b);
1.ViewGroup的layout()是final的,所以ViewGroup子类不可重写该方法。
2.ViewGroup的layout()实际上有调用super.layout(),即调用View的layout()。
3.ViewGroup的onLayout()是抽象的,所以ViewGroup的子类必须重写该方法。
4.ViewGroup的子类像LinearLayout,FrameLayout,RelativeLayout等都重写了onLayout()方法,并且它们
的onLayout()方法里面都会调用了child.layout()方法。
5.View的layout()里面调用了onLayout(),onLayout()为空方法,所以View的子类是可以重写onLayout()方法的,一般情况下是不会重写onLayout()方法的。ps: TextView有重写,ImageView没有重写。
ViewRootImpl.doTraversal()->
ViewRootImpl.performTraversals()->
//开始布局
ViewRootImpl.performLayout()->
PhoneWindow$DecorView执行ViewGroup.layout()->
PhoneWindow$DecorView.onLayout()->
PhoneWindow$DecorView执行child.layout()->
LinearLayout执行ViewGroup.layout()->
LinearLayout.onLayout()->
LinearLayout执行child.layout()->
FrameLayout执行ViewGroup.layout()->
FrameLayout.onLayout()->
FrameLayout执行child.layout()->
RelativeLayout执行ViewGroup.layout()->
RelativeLayout.onLayout()->
RelativeLayout执行child.layout()->
TextView执行View.layout()->
TextView.onLayout()
public void draw(Canvas canvas) {
...//省略代码
onDraw(canvas);
dispatchDraw(canvas);
}
protected void onDraw(Canvas canvas) {}
protected void dispatchDraw(Canvas canvas) {}
protected void dispatchDraw(Canvas canvas) {...drawChild()}
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
return child.draw(canvas, this, drawingTime);
}
1.drawChild方法是在ViewGroup的dispatchDraw()方法里面执行的。
2.发现LinearLayout和ViewPager重写了onDraw(),因为LinearLayout分横向和纵向布局。
一般情况下ViewGroup子类不会轻易重写draw(),onDraw(),dispatchDraw();即一般调用View.draw()
View.onDraw()空方法,ViewGroup.drawChild()。
3.一般情况下,View的子类都应该重写onDraw()方法。
ViewRootImpl.doTraversal()->
ViewRootImpl.performTraversals()->
//开始绘制
ViewRootImpl.performDraw()->
PhoneWindow$DecorView执行View.draw()->
PhoneWindow$DecorView.onDraw()->
PhoneWindow$DecorView执行ViewGroup.dispatchDraw()->
PhoneWindow$DecorView执行ViewGroup.drawChild()->
LinearLayout执行View.draw()->
LinearLayout执行ViewGroup.dispatchDraw()->
LinearLayout执行ViewGroup.drawChild()->
FrameLayout执行View.draw()->
FrameLayout执行ViewGroup.dispatchDraw()->
FrameLayout执行ViewGroup.drawChild()->
RelativeLayout执行View.draw()->
RelativeLayout执行ViewGroup.dispatchDraw()->
RelativeLayout执行ViewGroup.drawChild()->
TextView执行View.draw()->
TextView.onDraw()
Android中View的量算、布局及绘图机制
Android应用层View绘制流程与源码分析
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/View.java
https://github.com/android/platform_frameworks_base/blob/master/core/java/android/view/ViewGroup.java