PreferenceFragmentCompatでPreferenceCategoryの見た目がなんか違う問題

2016/11/26

とあるアプリの設定画面をPreferenceActivityからPreferenceFragmentCompatに変更したらハマったので顛末を。

PreferenceFragmentCompatはSupport Libraryで提供されているのでbuild.gradleでdependencyに追加します。

compile 'com.android.support:preference-v14:25.0.0'

PreferenceFragmentCompatベースで一通り実装したらstyleでthemeを設定してあげます。

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>

これでOK、と思いきや、Android4.1端末だとPreferenceCategoryのレイアウトが変です。 色の設定が反映されないし、左側、上側のマージンが無くなっちゃいました。

試していないですが4.1特有じゃなくてほかのバージョンでも起きそう。6.0では大丈夫だったので、特定バージョン以下はNGってパターンだと思います。

ググるとandroid:listSeparatorTextViewStyleをカスタムする、という方法が見つかったんですがうまくいかず。

さらに調べて見つけたandroid - Set Title style for PreferenceCategory in PreferenceFragmentCompat - Stack Overflowによると

  • マテリアルデザインを適用したPreferenceCategoryはandroid:listSeparatorTextViewStyleを使わず、システムデフォルトのスタイルを適用してしまう
  • PreferenceCategoryに独自のLayoutを適用すべし
  • 独自Layoutには適切なstyleを当てろ

ということのようです。これに従ってみるとうまくいきました。

PreferenceCategoryは実質TextViewなので、view_custom_preference_category.xmlという名前でTextViewベースの独自Layoutを作ります。

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
          android:id="@android:id/title"
          style="@style/CustomPreferenceCategoryText"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"/>

styleのほうはこうなりました。PreferenceThemeOverlay.v14.MaterialをベースにPreferenceCategoryだけ弄る感じですね。

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

    <item name="preferenceTheme">@style/AppTheme.PreferenceStyle</item>
</style>

<style name="AppTheme.PreferenceStyle" parent="@style/PreferenceThemeOverlay.v14.Material">
    <item name="preferenceCategoryStyle">@style/AppTheme.CustomPreferenceCategory</item>
</style>

<style name="AppTheme.CustomPreferenceCategory" parent="@style/Preference.Category">
    <item name="android:layout">@layout/view_custom_preference_category</item>
</style>

<style name="CustomPreferenceCategoryText" parent="@android:style/Widget.TextView">

    <item name="android:textSize">16sp</item>
    <item name="android:textStyle">bold</item>
    <item name="android:textColor">@color/colorAccent</item>
    <item name="android:layout_marginTop">12dp</item>
    <item name="android:layout_marginBottom">8dp</item>
    <item name="android:layout_marginLeft">16dp</item>
</style>

CustomPreferenceCategoryTextにいい感じのstyleを定義すればOKです。上記はMaterial Designのデフォルトからはちょっと変えてあります。

これでPreferenceFragmentCompatを使った設定画面が作れるようになりました。

QiitaにSupportLibrary23.0.1のPreferenceFragmentCompatを試して死んだメモ - Qiitaという記事があったり、Gericop/Android-Support-Preference-V7-Fixというpreference-v7 support libraryのバグに対応するためのOSSライブラリがあったり、PreferenceFragment周りは厄介なんですね...




関連(するかもしれない)記事


おススメ