Android で PreferenceActivity 使ってみた

More than 1 year has passed since last update.


PreferenceActivity とは

Android アプリにおいて、アプリの設定をする機能を提供してる。

設定は階層構造になったたくさん項目があったりするが、一個の Activity でそれを表現できる 1。ListView を継承していて、設定項目用の xml なども容易に定義できるし、保存された設定項目を SharedPreferences でアプリのどこからでも呼び出せるようになる。タブレット端末など大きめな端末を横長に向けたときに、1層目がサイドメニューになり、2層目を右側に表示するというようなことができるようになる。

(たぶん)


使ってみた

Android のバージョンは 7で作業しています。


作業してみた順

この分野については詳しくないので、とりあえず新しいアプリを作った。最初に Activity を選ぶところで Settings Activity っていうのを選ぶ。スクリーンショット 2018-03-15 20.06.37.png

これで、設定項目を変更するだけのアプリが作れる。ビルドすればアプリを動かせる。楽しい

既存アプリに追加もしたくてどうするか迷ったが、自動で生成されたコードのうちのどれが必要かイマイチ分からなくて萎えたので、 Android Studio の New -> Activity -> Settings Activity から、こちらも自動生成でずどんと追加してみた。

んで、いろいろいじっていくと。

ここに詳しく書いてある。

https://developer.android.com/guide/topics/ui/settings.html?hl=ja


構造

サンプルで作ると、2層構造になる。

-+- General

| |- Enable social recommendations
| |- Display name
| `- Add friends to messages
|
|
|- Notifications
| |- New message notifications
| |- ...
|
|
`- Data Sync
|- Sync frequency
|- ...

1層目
2層目

スクリーンショット 2018-03-15 20.39.04.png
スクリーンショット 2018-03-15 20.39.14.png


作られたファイル


  • res/xml/pref_headers.xml 上記の1層目、 General / Notifications / Data Sync の3つを選ぶ ListView が出てくる。編集の必要あり

  • その他の res/xml/pref_*.xml 2層目の各項目に対応。編集の必要あり

  • res/drawable/*.xml アイコン。必要なやつだけコミットすればよし

  • activity/AppCompatPreferenceActivity.java いろいろ書いてある親クラス (後述)

  • activity/SettingsActivity.java 設定を変更したときの動きなどを記述する。編集の必要あり

Activity が一個というのが面白いと思った。


実装したメモ


Activity で要らなかったやつ

AppCompatPreferenceActivity を継承して SettingsActivity を作ったが、 AppCompatPreferenceActivity にあった実装のうち動かすのに必要だったのは

public class SettingsActivity extends PreferenceActivity {

private AppCompatDelegate mDelegate;

private AppCompatDelegate getDelegate() {
if (mDelegate == null) {
mDelegate = AppCompatDelegate.create(this, null);
}
return mDelegate;
}

public ActionBar getSupportActionBar() {
return getDelegate().getSupportActionBar();
}

これだけだった。

もう一個親クラスの PreferenceActivity を読んでみると override しろってたくさん書いてあるから、削除するともしかしたら落ちるかもしれない。けど、意味のわからない 300行のコードを「自動生成されたから」というだけでコミットしてしまうのはちょっと気が引けたので、削ってしまった。


headers から、他のアクティビティに飛ばす

設定画面を本格的に作るより前に、一つだけ既に画面があったので、項目のうちの一つはそこに飛ばしたかった


pref_headers.xml

<preference-headers xmlns:android="http://schemas.android.com/apk/res/android">

<header
android:title="@string/foo_bar">
<intent
android:action="android.intent.action.MAIN"
android:targetPackage="com.example.project"
android:targetClass="com.example.project.activity.FooBarActivity" >
</intent>

こうやって書くと FooBarActivity が開ける。値を渡したり戻り値をとったりすることもできるっぽいが、特に必要がなくてやっていない。


headers の画面の左上矢印から、他のアクティビティに戻る

サンプルコードでは FragmentonOptionsItemSelected が実装されているが、これは2層目の矢印の挙動を定めている。1層目の headers の画面での矢印に対して動作をさせるためには、 Activity に onOptionsItemSelected を足す。

public class SettingsActivity extends PreferenceActivity {

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}

こちらに教わりました。 http://rikisha-android.hatenablog.com/entry/2014/04/04/202207


保存した設定値を呼び出す

使いたいところで

        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);

sharedPref.getBoolean("foo_bar_boolean_setting", false)

こう書いちゃう。楽チン。

アプリ内のデータ保存って... sqlite? どうやってアクセスするんだっけ?みたいなレベルの自分には非常に嬉しい。


現在の設定内容をテキストで表示する

ことができる。これから挑戦。


変更後、データをサーバに保存する

これから挑戦。きっと Fragment に何かを書くんだ。


困ったこと


不明点1: 1層目 preference-headers の各行の高さを変えたりラインを入れたりできない

ちょっと見づらいのだがどうすりゃいいのか分からなかった....諦め気味。

1層目
2層目

スクリーンショット 2018-03-15 20.39.04.png
スクリーンショット 2018-03-15 20.39.14.png

2層目はきれいなのに。


不明点2: 1層目で選択時にダイアログを表示したい

ログアウトっていう項目を作ろうと思ったが、特に2層目はないので、「ログアウトしますか?」ってダイアログを表示したい。

こちらは調査中





  1. むしろ煩雑になるような気もするけどどうなんでしょう。