設定を編成する   Part of Android Jetpack.

設定画面が大規模で複雑になると、ユーザーが変更しようとしている特定の設定を見つけるのが難しくなります。 Preference Library には、設定画面の編成方法を改善するための次のような手段が用意されています。

Preference カテゴリ

1 つの画面に複数の関連した Preferences がある場合、PreferenceCategory によりそれらをグループ化することができます。 PreferenceCategory は、カテゴリのタイトルを表示し、カテゴリを視覚的に分離します。

XML で PreferenceCategory を定義するには、下記に示すように、Preference タグを PreferenceCategory で囲みます。

<androidx.preference.PreferenceScreen
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <PreferenceCategory
        app:key="notifications_category"
        app:title="Notifications">

        <SwitchPreferenceCompat
            app:key="notifications"
            app:title="Enable message notifications"/>

    </PreferenceCategory>

    <PreferenceCategory
        app:key="help_category"
        app:title="Help">

        <Preference
            app:key="feedback"
            app:summary="Report technical issues or suggest new features"
            app:title="Send feedback"/>

    </PreferenceCategory>

</androidx.preference.PreferenceScreen>
図 1. 複数のカテゴリに分類した Preference。

階層を複数画面に分割する

Preferences や異なるカテゴリが多数ある場合、それらを別々の画面に表示することができます。 各画面は、それぞれ別個の独自階層を伴う PreferenceFragmentCompat でなければなりません。 初期画面の Preferences に、関連する Preferences を含むサブ画面へのリンクを用意することができます。

図 2 に示すのは、2 つのカテゴリが含まれるシンプルな階層です。メッセージと同期。

図 2. カテゴリ 2 個のシンプルな階層。

図 3 に示すのは、Preferences の同じセットを複数画面に分割したものです。

図 3. 複数画面に分割した階層。

Preference で複数画面をリンクするには、XML の中で app:fragment を宣言するか、または Preference.setFragment() を使用できます。 下に示されているように、Preference がタップされた時点で起動する PreferenceFragmentCompat の完全なパッケージ名を設定します。

<Preference
        app:fragment="com.example.SyncFragment"
        .../>

Fragment が関連付けられた Preference をユーザーがタップすると、インターフェース メソッド PreferenceFragmentCompat.OnPreferenceStartFragmentCallback.onPreferenceStartFragment() が呼び出されます。 これが新しい画面を処理するメソッドであり、それを囲む Activity の中で実装する必要があります。

典型的な実装は、次のようになります。

Kotlin

class MyActivity : AppCompatActivity(),
    PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {

    ...

    override fun onPreferenceStartFragment(caller: PreferenceFragmentCompat, pref: Preference): Boolean {
        // Instantiate the new Fragment
        val args = pref.extras
        val fragment = supportFragmentManager.fragmentFactory.instantiate(
                classLoader,
                pref.fragment,
                args)
        fragment.arguments = args
        fragment.setTargetFragment(caller, 0)
        // Replace the existing Fragment with the new Fragment
        supportFragmentManager.beginTransaction()
                .replace(R.id.settings_container, fragment)
                .addToBackStack(null)
                .commit()
        return true
    }
}

Java

public class MyActivity extends AppCompatActivity implements
        PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {

    ...

    @Override
    public boolean onPreferenceStartFragment(PreferenceFragmentCompat caller, Preference pref) {
        // Instantiate the new Fragment
        final Bundle args = pref.getExtras();
        final Fragment fragment = getSupportFragmentManager().getFragmentFactory().instantiate(
                getClassLoader(),
                pref.getFragment(),
                args);
        fragment.setArguments(args);
        fragment.setTargetFragment(caller, 0);
        // Replace the existing Fragment with the new Fragment
        getSupportFragmentManager().beginTransaction()
                .replace(R.id.settings_container, fragment)
                .addToBackStack(null)
                .commit();
        return true;
    }
}

PreferenceScreen

同じ XML リソース内で、ネストした <PreferenceScreen> を使用することにより、ネストした階層を宣言することはサポートされていません。 代わりに、ネストした Fragment オブジェクトを使用してください。

別々の Activity を使用する

別の方法として、各画面を大幅にカスタマイズする必要がある場合、または画面間での全面的な Activity 遷移を行う場合、PreferenceFragmentCompat ごとに別個の Activity を使用することができます。 そのようにすることにより、各 Activity とそれに対応する設定画面を全面的にカスタマイズすることができます。 ほとんどのアプリケーションでは、これは勧められていません。前述のように Fragments を使用するようにしてください。

Preference から Activities を起動することについては、Preference actions をご覧ください。