PreferenceFragmentCompat、とても便利ですが痒いところに手が届きません。特にこのような設定レイアウトはよく見ますが、標準では用意されていません。
完成図 | 参考レイアウト(Twitter) |
---|---|
![]() |
![]() |
実装
Android Studioに用意されているテンプレートSetting Activity
を元に作っていきます。
1. 土台となるコード
PreferenceFragmentCompatはxmlで背景色を指定する方法がありませんので、setBackgroundColor
を使用して背景色を変更します。
SettingsFragment.kt
package com.sakusaku.test
import android.graphics.Color
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.preference.PreferenceFragmentCompat
class SettingsFragment : PreferenceFragmentCompat() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = super.onCreateView(inflater, container, savedInstanceState)
// 背景色の設定
view?.setBackgroundColor(Color.parseColor("#F5F5F5"))
return view
}
}
次に設定画面のレイアウトを作成します。
res/layout/root_preferences.xml
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference
android:defaultValue="online"
android:entries="@array/entries_preference_status"
android:entryValues="@array/values_preference_status"
android:key="preference_status"
android:layout="@layout/custom_preference"
android:title="@string/preference_status"
app:useSimpleSummaryProvider="true" />
<ListPreference
android:defaultValue="short"
android:entries="@array/entries_preference_scan_period"
android:entryValues="@array/values_preference_scan_period"
android:key="preference_scan_period"
android:layout="@layout/custom_preference"
android:title="@string/preference_scan_period"
app:useSimpleSummaryProvider="true" />
<PreferenceScreen
android:layout="@layout/preference_diver"
android:selectable="false" />
<PreferenceScreen
android:key="preference_notice"
android:layout="@layout/custom_preference"
android:title="@string/preference_notice" />
<PreferenceScreen
android:key="preference_about"
android:layout="@layout/custom_preference"
android:title="@string/preference_about" />
<PreferenceScreen
android:key="preference_send_feedback"
android:layout="@layout/custom_preference"
android:title="@string/preference_send_feedback" />
<PreferenceScreen
android:key="preference_privacy_policy"
android:layout="@layout/custom_preference"
android:title="@string/preference_privacy_policy" />
<PreferenceScreen
android:key="preference_oss_license"
android:layout="@layout/custom_preference"
android:title="@string/preference_oss_license" />
</PreferenceScreen>
リソース等は下記の通りです。
res/values/string.xml
<resources>
<string name="preference_status">ステータスを設定</string>
<string name="preference_scan_period">スキャンの間隔</string>
<string name="preference_notice">お知らせ</string>
<string name="preference_about">このアプリについて</string>
<string name="preference_send_feedback">フィードバックを送る</string>
<string name="preference_privacy_policy">プライバシーポリシー</string>
<string name="preference_oss_license">オープンソースライセンス</string>
</resources>
res/values/array.xml
<resources>
<string-array name="entries_preference_status">
<item>オンライン</item>
<item>オフライン</item>
</string-array>
<string-array name="values_preference_status">
<item>online</item>
<item>offline</item>
</string-array>
<string-array name="entries_preference_scan_period">
<item>短い</item>
<item>中間</item>
<item>長い</item>
</string-array>
<string-array name="values_preference_scan_period">
<item>short</item>
<item>middle</item>
<item>long</item>
</string-array>
</resources>
2. PreferenceScreen
とListPreference
用のカスタムレイアウトを作成
Preferenceには標準で透過色が設定されているため、白の背景色を設定したカスタムレイアウトを作成します。
元のレイアウトはAOSP上に公開されています。
res/layout/custom_preference.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2014 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<!-- Layout for a Preference in a PreferenceActivity. The
Preference is able to place a specific widget for its particular
type in the "widget_frame" layout. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:baselineAligned="false"
android:clipToPadding="false"
android:foreground="?attr/selectableItemBackground"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<LinearLayout
android:id="@+android:id/icon_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="-4dp"
android:gravity="start|center_vertical"
android:minWidth="60dp"
android:orientation="horizontal"
android:paddingStart="0dp"
android:paddingTop="4dp"
android:paddingEnd="12dp"
android:paddingBottom="4dp">
<com.android.internal.widget.PreferenceImageView
android:id="@+android:id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="48dp"
android:maxHeight="48dp" />
</LinearLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<TextView
android:id="@+android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem" />
<TextView
android:id="@+android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+android:id/title"
android:layout_alignStart="@+android:id/title"
android:ellipsize="end"
android:maxLines="10"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary" />
</RelativeLayout>
<LinearLayout
android:id="@+android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="end|center_vertical"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingEnd="0dp" />
</LinearLayout>
android:id
が赤色に表示されますが問題ありません。
3. Preference同士の隙間(区切り)を表示
Preferenceの区切りごとに隙間を開けるカスタムレイアウトを作成します。
res/layout/preference_diver.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:layout_width="match_parent"
android:layout_height="16dp" />
</LinearLayout>
表示の際はPreferenceScreen
に上記のレイアウトを追加します。android:selectable="false"
を指定することでクリックを無効化出来ます。
res/layout/custom_preference.xml
<PreferenceScreen
android:layout="@layout/preference_diver"
android:selectable="false" />