建立片段

片段代表的是在一個活動中使用者介面裡模組的部分。片段具有其生命週期、會接收其本身的輸入事件,而在其具有的活動執行時,您可以新增或移除片段。

本文件將說明如何建立片段,並將其納入活動中。

設定環境

片段需要一個 AndroidX 片段程式庫的依附元件。您必須將 Google Maven 存放區新增至專案的 settings.gradle 檔案中,才能納入這個依附元件。

Groovy

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        ...
    }
}

Kotlin

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        ...
    }
}

若要在專案中納入 AndroidX 片段程式庫,請在應用程式的 build.gradle 檔案中新增以下依附元件:

Groovy

dependencies {
    def fragment_version = "1.8.5"

    // Java language implementation
    implementation "androidx.fragment:fragment:$fragment_version"
    // Kotlin
    implementation "androidx.fragment:fragment-ktx:$fragment_version"
}

Kotlin

dependencies {
    val fragment_version = "1.8.5"

    // Java language implementation
    implementation("androidx.fragment:fragment:$fragment_version")
    // Kotlin
    implementation("androidx.fragment:fragment-ktx:$fragment_version")
}

建立片段類別

若要建立一個片段,請擴充 AndroidX Fragment 類別,並覆寫其方法,插入應用程式的邏輯,做法與建立 Activity 類別類似。若要建立一個用來定義其專屬版面配置的最小片段,請為基礎建構函式提供片段的版面配置資源,作法如以下範例所示:

Kotlin

class ExampleFragment : Fragment(R.layout.example_fragment)

Java

class ExampleFragment extends Fragment {
    public ExampleFragment() {
        super(R.layout.example_fragment);
    }
}

Fragment 程式庫也提供較為特殊的片段基礎類別:

DialogFragment
顯示浮動對話方塊。除了使用 Activity 類別的對話方塊輔助方法以外,運用這個類別建立對話方塊是很不錯的替代方法,因為片段會自動處理 Dialog 的建立及清理作業。詳細內容請參閱透過 DialogFragment 顯示對話方塊
PreferenceFragmentCompat
以清單的形式顯示 Preference 物件的階層清單。您可以使用 PreferenceFragmentCompat 為應用程式建立設定畫面

在活動中新增片段

一般來說,片段必須嵌入在 AndroidX FragmentActivity 中,才能為該活動的版面配置提供部分使用者介面。FragmentActivityAppCompatActivity 的基礎類別,因此若您已將 AppCompatActivity 設為子類別,用來在應用程式中提供回溯相容性,就不必變更活動的基礎類別。

您可以將片段新增至活動的檢視區塊階層,方法是在活動的版面配置檔案中定義片段;或是在活動的版面配置檔案中定義片段容器,然後以程式輔助方式從活動中新增片段。無論是哪一種作法,您都必須新增 FragmentContainerView,以定義片段在活動的檢視區塊階層中的位置。強烈建議您一律使用 FragmentContainerView 做為片段的容器,因為 FragmentContainerView 具有特別針對片段的修正內容,而這是其他檢視區塊群組(例如 FrameLayout)所沒有的。

透過 XML 新增片段

如果要對活動版面配置的 XML 宣告新增片段,請使用 FragmentContainerView 元素。

以下是含有單一 FragmentContainerView 的活動版面配置範例:

<!-- res/layout/example_activity.xml -->
<androidx.fragment.app.FragmentContainerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:name="com.example.ExampleFragment" />

android:name 屬性可指定 Fragment 的類別名稱以用來執行個體化。當系統載入活動的版面配置時,指定的片段就會執行個體化;新執行個體化的片段中 onInflate() 會被呼叫,接著會建立 FragmentTransaction 將片段新增至 FragmentManager

透過程式輔助方式新增片段

如要透過程式輔助方式在活動的版面配置中新增片段,則版面配置應包含 FragmentContainerView 做為片段的容器,如以下範例所示:

<!-- res/layout/example_activity.xml -->
<androidx.fragment.app.FragmentContainerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragment_container_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

與 XML 作法不同的是,FragmentContainerView 中沒有使用到 android:name 屬性,因此沒有特定的片段會自動執行個體化。反之,FragmentTransaction 則被用來將片段執行個體化,並將其新增至活動的版面配置中。

活動執行時,可以對片段進行交易,例如新增、移除或取代片段。您可以在 FragmentActivity 中取得 FragmentManager 的例項,可用於建立 FragmentTransaction。接著,您可以使用 FragmentTransaction.add(),在活動的 onCreate() 方法中將片段例項化,傳入版面配置中容器的 ViewGroup ID,以及您要新增的片段類別;然後才提交交易。如以下範例所示:

Kotlin

class ExampleActivity : AppCompatActivity(R.layout.example_activity) {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (savedInstanceState == null) {
            supportFragmentManager.commit {
                setReorderingAllowed(true)
                add<ExampleFragment>(R.id.fragment_container_view)
            }
        }
    }
}

Java

public class ExampleActivity extends AppCompatActivity {
    public ExampleActivity() {
        super(R.layout.example_activity);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                .setReorderingAllowed(true)
                .add(R.id.fragment_container_view, ExampleFragment.class, null)
                .commit();
        }
    }
}

在前一個範例中,請注意,只有當 savedInstanceStatenull 時,才會建立片段交易。這是為了確保在首次建立活動時,只會新增一次片段。當設定變更而且重新建立了活動時,savedInstanceState 不再是 null,且不必再次新增片段,因為片段會自動從 savedInstanceState 中還原。

如果片段需要一些初始資料,可以在呼叫 FragmentTransaction.add() 時提供 Bundle 將引數傳送至片段,如下所示:

Kotlin

class ExampleActivity : AppCompatActivity(R.layout.example_activity) {
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (savedInstanceState == null) {
            val bundle = bundleOf("some_int" to 0)
            supportFragmentManager.commit {
                setReorderingAllowed(true)
                add<ExampleFragment>(R.id.fragment_container_view, args = bundle)
            }
        }
    }
}

Java

public class ExampleActivity extends AppCompatActivity {
    public ExampleActivity() {
        super(R.layout.example_activity);
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null) {
            Bundle bundle = new Bundle();
            bundle.putInt("some_int", 0);

            getSupportFragmentManager().beginTransaction()
                .setReorderingAllowed(true)
                .add(R.id.fragment_container_view, ExampleFragment.class, bundle)
                .commit();
        }
    }
}

接著透過呼叫 requireArguments() 從片段中擷取引數 Bundle,並使用適當的 Bundle getter 方法擷取每個引數。

Kotlin

class ExampleFragment : Fragment(R.layout.example_fragment) {
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        val someInt = requireArguments().getInt("some_int")
        ...
    }
}

Java

class ExampleFragment extends Fragment {
    public ExampleFragment() {
        super(R.layout.example_fragment);
    }

    @Override
    public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
        int someInt = requireArguments().getInt("some_int");
        ...
    }
}

另請參閱

片段交易,FragmentManager 則會在片段管理員指南中詳細說明。