布局专栏里面一直缺一篇FrameLayout的文章。
DecorView的完整路径,是com.android.internal.policy.DecorView。Android studio中双击shift搜索,能找到DecorView的源代码,如下图:

从源码可以看到,DecorView extends FrameLayout:

Activity中,View树的根布局就是DecorView。如下图,DecorView内部分了三次,最底层是一个LinearLayout,它上面覆盖了一个id为navigationBarBackground的View,就是底部导航栏。最上面是一个id为statusBarBackground的View,也就是顶部状态栏。这是明显的分层布局,所以用了FrameLayout。
具体代码见:Fragment系列:使用FrameLayout动态加载
从上图中,我们可以看大一个id为content的FragmentLayout,他内部的RelativeLayout是我自己写的activity_main.xml文件的根布局。 切换到Project模式——>找到External Libraries——>对应的编译API,例如Android API 32 Platform ——>res ——>layout文件夹下——>找到R.layout.screen_simple
打开再核对下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<ViewStub android:id="@+id/action_mode_bar_stub"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="?attr/actionBarTheme" />
<FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:foregroundInsidePadding="false"
android:foregroundGravity="fill_horizontal|top"
android:foreground="?android:attr/windowContentOverlay" />
LinearLayout>
这里使用FrameLayout的原因和加载Fragment是一致的,因为Activity和Fragment传递过来的都是单个布局。FrameLayout只充当一个容器。
https://developer.android.google.cn/reference/android/widget/FrameLayout
英文原文还是更好理解一些:
FrameLayout is designed to block out an area on the screen to display a single item. Generally, FrameLayout should be used to hold a single child view, because it can be difficult to organize child views in a way that’s scalable to different screen sizes without the children overlapping each other.
You can, however, add multiple children to a FrameLayout and control their position within the FrameLayout by assigning gravity to each child, using the android:layout_gravity attribute.
Child views are drawn in a stack, with the most recently added child on top. The size of the FrameLayout is the size of its largest child (plus padding), visible or not (if the FrameLayout’s parent permits). Views that are View.GONE are used for sizing only if setConsiderGoneChildrenWhenMeasuring() is set to true.
这段介绍强调了single,也就是说FrameLayout的设计初衷是只显示单个item。
第二段话,讲到了,但是FrameLayout还是可以添加多个子view,然后用layout_gravity来控制位置。第三段话不太重要,不纠结。

FrameLayout讲到这个深度,对于平时使用,已经足够了。