Android中View的布局及绘图机制

为了研究Android中View的布局及绘图机制,我创建了一个非常简单的App,该App只有一个Activity,该Activity对应的layout如下所示:

<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”xmlns:tools=”http://schemas.android.com/tools” android:layout_width=”match_parent”android:layout_height=”match_parent” android:paddingLeft=”@dimen/activity_horizontal_margin”android:paddingRight=”@dimen/activity_horizontal_margin”android:paddingTop=”@dimen/activity_vertical_margin”android:paddingBottom=”@dimen/activity_vertical_margin” tools:context=”.MainActivity”><TextView android:text=”@string/hello_world” android:layout_width=”wrap_content”android:layout_height=”wrap_content” /></RelativeLayout>

该布局文件很简单,RelativeLayout下面就一个TextView。

我们启动App后,通过Hierarchy Viewer查看App中的布局层级,如下所示:

从上图我们可以看出,App的根结点是PhoneWindow$DecorView,此处的$表示DecorView是PhoneWindow下面的内部类实例。PhoneWindow$DecorView下面有三个child,分别是LinearLayout实例、View@49da043和View@44ff410。View@49da043表示的是navigationBarBackground,View@44ff410表示的是statusBarBackground。LinearLayout下面有两个child,分别是ViewStub实例和FrameLayout实例,其中ViewStub不需要绘制,所以我们在下面的讨论中可以直接对其忽略。FrameLayout下有一个child,RelativeLayout实例,该RelativeLayout实例对应的就是布局文件activity_main.xml中的RelativeLayout,RelativeLayout下有一个child,即TextView。

以上提到的控件都是View的实例,有的则是ViewGroup的实例,ViewGroup继承自View,PhoneWindow$DecorView、RelativeLayout、FrameLayout、RelativeLayout都直接或间接继承自ViewGroup,只有ViewGroup实例才能有子节点。

当我们在onCreate()方法中调用setContentView(R.layout.activity_main)方法后,Android会从layout的树形结构中自上而下开始对所有的View进行量算、布局、绘图,具体来说经过以下过程:

以下是涉及到的相关类的源码: View源码 ViewGroup源码 ViewRootImpl源码 PhoneWindow$DecorView源码 LinearLayout源码 FrameLayout源码 RelativeLayout源码 TextView源码

量算

关于Measure:

以下是Android对所有View自上而下量算的调用过程:

这样整个View树自上而下的量算过程就结束了,经过量算Android知道了各个View想要渲染的尺寸大小,即宽度和高度信息。

关于量算中measure()和onMeasure()方法的一些细节会另外写博文介绍。

布局

关于Layout:

Android中的布局过程与之前上面提到的量算过程很类似,以下是Android对所有View自上而下布局的调用过程:

这样整个View树自上而下的布局过程就结束了,经过布局Android知道了各个View在其父控件中的位置。

绘图

关于Draw:

绘图的前提是已经对View进行了量算和布局,View通过调用draw()方法进行绘图,绘图的目的就是让View在UI界面上呈现出来。

View的draw()方法中会依次onDraw()和dispatchDraw()方法,View类本身的onDraw()和dispatchDraw()方法都是空方法。View的子类不应该重写draw()方法,如果需要的话应该按具体情况选择重写onDraw()方法或dispatchDraw()方法,,具体来说:

Android中的绘图过程与之前上面提到的量算、布局过程类似,以下是Android对所有View进行自上而下绘图的调用过程:

总结

当我们在onCreate()方法中调用setContentView(R.layout.activity_main)方法后,Android会从layout的树形结构中自上而下开始对所有的View进行量算、布局、绘图:

希望本文对大家理解Android中View的布局和绘图机制有所帮助。

相关阅读: Android相关博文整理汇总

一直觉得人应该去旅行,在年轻的时候,

Android中View的布局及绘图机制

相关文章:

你感兴趣的文章:

标签云: