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. むしろ煩雑になるような気もするけどどうなんでしょう。 

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.