PreferenceActivity とは
Android アプリにおいて、アプリの設定をする機能を提供してる。
設定は階層構造になったたくさん項目があったりするが、一個の Activity でそれを表現できる 1。ListView を継承していて、設定項目用の xml なども容易に定義できるし、保存された設定項目を SharedPreferences
でアプリのどこからでも呼び出せるようになる。タブレット端末など大きめな端末を横長に向けたときに、1層目がサイドメニューになり、2層目を右側に表示するというようなことができるようになる。
(たぶん)
使ってみた
Android のバージョンは 7で作業しています。
作業してみた順
この分野については詳しくないので、とりあえず新しいアプリを作った。最初に Activity を選ぶところで Settings Activity
っていうのを選ぶ。
これで、設定項目を変更するだけのアプリが作れる。ビルドすればアプリを動かせる。楽しい
既存アプリに追加もしたくてどうするか迷ったが、自動で生成されたコードのうちのどれが必要かイマイチ分からなくて萎えたので、 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層目 |
---|---|
![]() |
![]() |
作られたファイル
- 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 から、他のアクティビティに飛ばす
設定画面を本格的に作るより前に、一つだけ既に画面があったので、項目のうちの一つはそこに飛ばしたかった
<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 の画面の左上矢印から、他のアクティビティに戻る
サンプルコードでは Fragment
に onOptionsItemSelected
が実装されているが、これは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層目 |
---|---|
![]() |
![]() |
2層目はきれいなのに。
不明点2: 1層目で選択時にダイアログを表示したい
ログアウトっていう項目を作ろうと思ったが、特に2層目はないので、「ログアウトしますか?」ってダイアログを表示したい。
こちらは調査中
-
むしろ煩雑になるような気もするけどどうなんでしょう。 ↩