[Android] PreferenceFragmentで設定画面を作る

非推奨

PreferenceFragmentはAPI level 28で非推奨になりました。
代わりにPreferenceFragmentCompatを使ってください。
PreferenceFragmentCompatについてはこちらで↓
mnoqlo.hatenablog.com




設定項目をタップするとページ(Fragment)を切り替える設定画面(?)を作ってみます。

完成図

f:id:mnoqlo:20171028064808p:plain

foo設定をクリックすると
f:id:mnoqlo:20171028064815p:plain

コード

SettingsActivity.java

public class SettingsActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_settings);

        // Toolbarにタイトルを設定
        ((Toolbar) findViewById(R.id.toolbar)).setTitle("設定");

        // fragment_container(FrameLayout)部分にMainPreferenceFragmentを挿入
        getFragmentManager().beginTransaction().replace(R.id.fragment_container, MainPreferenceFragment.newInstance()).commit();
    }

}


activity_settings.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- themeは各自のテーマを -->
    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:theme="@style/ToolbarTheme" />

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/toolbar" />

</RelativeLayout>


MainPreferenceFragment.java

public class MainPreferenceFragment extends PreferenceFragment implements Preference.OnPreferenceClickListener {

    public static MainPreferenceFragment newInstance() {
        return new MainPreferenceFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preference_main);

        // findPreferenceでkeyに対応するPreferenceを取得し、それがクリックされた時のリスナーを登録する
        // リスナーはこのクラス自体にimplementsしてるのでthis
        findPreference("preference_foo").setOnPreferenceClickListener(this);
        findPreference("preference_bar").setOnPreferenceClickListener(this);
    }


    // リスナー部分
    @Override
    public boolean onPreferenceClick(Preference preference) {
        // keyを見てクリックされたPreferenceを特定
        switch (preference.getKey()) {
            case "preference_foo":
                transitionFragment(FooPreferenceFragment.newInstance());
                break;
            case "preference_bar":
                transitionFragment(BarPreferenceFragment.newInstance());
                break;
        }
        // おそらくですが、クリックした時に反応するリスナーが複数ある場合、ここをtrueにするとこれより後のリスナーが反応しなくなります
        return false;
    }

    private void transitionFragment(PreferenceFragment nextPreferenceFragment) {
        // replaceによるFragmentの切り替えと、addToBackStackで戻るボタンを押した時に前のFragmentに戻るようにする
        getFragmentManager()
                .beginTransaction()
                .addToBackStack(null)
                .replace(R.id.fragment_container, nextPreferenceFragment)
                .commit();
    }

}


Preferenceのxmlファイルは一般的にres/xml以下に作成するみたいですたぶん
preference_main.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory
        android:title="設定">

        <PreferenceScreen
            android:title="foo設定"
            android:key="preference_foo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <PreferenceScreen
            android:title="bar設定"
            android:key="preference_bar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </PreferenceCategory>

</PreferenceScreen>


FooPreferenceFragment.java

public class FooPreferenceFragment extends PreferenceFragment {

    public static FooPreferenceFragment newInstance() {
        return new FooPreferenceFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preference_foo);
    }

}


preference_foo.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory
        android:title="foo設定">

        <PreferenceScreen
            android:title="foo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </PreferenceCategory>

</PreferenceScreen>


以下barはfooと名前が変わっただけです
BarPreferenceFragment.java

public class BarPreferenceFragment extends PreferenceFragment {

    public static BarPreferenceFragment newInstance() {
        return new BarPreferenceFragment();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        addPreferencesFromResource(R.xml.preference_bar);
    }

}


preference_bar.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">

    <PreferenceCategory
        android:title="bar設定">

        <PreferenceScreen
            android:title="bar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </PreferenceCategory>

</PreferenceScreen>

今回はPreferenceScreenをクリックした時のFragmentページ遷移のみです。
より具体的な設定項目の作り方に関しては、それぞれのPreference名(「ListPreference」や「EditTextPreference」等)で検索してみてください。
もし要望があればそちらも書きます。
そりでわ皆さん、良きAndroidライフを~~~