markdown
我們為 activity 編寫的 layout 層級都在 android.id.content 這個 Android 內建的 layout id 之下,那 android.id.content 是不是 Activity 的 頂層 view 了呢?其實並不是的,它只是我們編寫的 layout 的 parent view 而已,當我們呼叫 [setContentView](https://developer.android.com/reference/android/app/Activity#setContentView(int)) 的時候,API 內部就將傳入的參數 layout id 放在 android.id.content 之下。
實際上 activity 的頂層 view 是一個叫 Decorview 的 FrameLayout,可以通過 API 取得。
protected void onCreate(Bundle savedInstanceState) {
View decorView = getWindoe().getDecorView();
}
Decorview 會在 Activity initialize 的時候被創建出來,不過它也不是被 Activity 直接持有,而是 Activity 的 Window 成員持有 Decorview,看下面這張圖會比較清楚它們之間的關係。
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjhrQ4YxP_wJRxZjtCCW_pFg2Mxmap7vF2SvD9p5_f29SDRjMzbWkFWAzX5HPJ5fvPwLdjhM4wS0CjoKkKit717nkn8Gfm2jJy3gwlHpIiSKAP87XFkj0kDw2RIEWb6BKDZMF6bTyWM5V5/s0/1.png)
雖然近來 Android 不斷提倡將 layout 層級扁平化以改善效能,但是你可以看到,就算我們寫的 layout 沒有任何嵌套,它也已經是第三層了,上面還有 android.id.content 和 Decorview 呢。
關於減少 layout 嵌套層級,在這裡順便提到使用 Fragment 時的一個小技巧,網路上很多範例,會在 activity layout xml 中放一個 FrameLayout 當成 fragment container。
FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
然後在 activity 中將 fragment 放入 container。
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState?) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
HeadlinesFragment firstFragment = new HeadlinesFragment();
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
其實並不需要自己再建立一個 FrameLayout 當作 container,android.id.content 已經是一個 FrameLayout,直接將 fragment 放到 android.id.content 就好,這樣可以減少一層 layout 嵌套。
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
public class MainActivity extends FragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState?) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_activity);
HeadlinesFragment firstFragment = new HeadlinesFragment();
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(android.id.content, firstFragment).commit();
}
}
---
* [Android: Full Screen UI with Transparent Status Bar](https://proandroiddev.com/android-full-screen-ui-with-transparent-status-bar-ef52f3adde63)
* [Activity 原理剖析 ](https://juejin.im/post/6844903978057072648)
* [android.R.id.content as container for Fragment](https://stackoverflow.com/questions/24712227/android-r-id-content-as-container-for-fragment)