我們為 activity 編寫的 layout 層級都在 android.id.content 這個 Android 內建的 layout id 之下,那 android.id.content 是不是 Activity 的 頂層 view 了呢?其實並不是的,它只是我們編寫的 layout 的 parent view 而已,當我們呼叫 setContentView 的時候,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,看下面這張圖會比較清楚它們之間的關係。
雖然近來 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();
- }
- }
沒有留言:
張貼留言