web-dev-qa-db-ja.com

Android.support.v7.preferenceライブラリを使用してカスタム設定を作成するにはどうすればよいですか?

私は少なくともapi 10をサポートしたいのですが、自分の好みをうまくスタイルできるようにしたいです。ヘッダーを持つことができるようにしたい(またはPreferenceScreensを表示したい)。 PreferenceActivityのカラーリングで完全にサポートされていないAppCompatは適合しないようです。したがって、AppCompatActivityPreferenceFragmentCompatを使用しようとしています。

public class Prefs extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (savedInstanceState == null)
            getSupportFragmentManager().beginTransaction()
                    .replace(Android.R.id.content, new PreferencesFragment())
                    .commit();
    }

    public static class PreferencesFragment extends PreferenceFragmentCompat {
        @Override public void onCreate(final Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);
        }

        @Override
        public void onDisplayPreferenceDialog(Preference preference) {
            // the following call results in a dialogue being shown
            super.onDisplayPreferenceDialog(preference);
        }

        @Override public void onNavigateToScreen(PreferenceScreen preferenceScreen) {
            // I can probably use this to go to to a nested preference screen
            // I'm not sure...
        }
    }
}

次に、フォントの選択を提供するカスタム設定を作成します。 PreferenceActivityを使用すると、簡単に

import Android.preference.DialogPreference;

public class FontPreference extends DialogPreference {

    public FontPreference(Context context, AttributeSet attrs) {super(context, attrs);}

    @Override protected void onPrepareDialogBuilder(Builder builder) {
        super.onPrepareDialogBuilder(builder);
        // do something with builder and make a Nice cute dialogue, for example, like this
        builder.setSingleChoiceItems(new FontAdapter(), 0, null);
    }
}

このようなxmlを使用して表示します

<my.app.FontPreference Android:title="Choose font" Android:summary="Unnecessary summary" />

しかし現在、Android.support.v7.preference.DialogPreferenceにはonPrepareDialogBuilderはありません。代わりに、PreferenceDialogFragmentCompatに移動しました。その使用方法に関する情報はほとんど見つかりませんでしたが、xmlから表示する方法がわかりません。 v14設定フラグメントには次のコードがあります。

public void onDisplayPreferenceDialog(Preference preference) {
    ...

    final DialogFragment f;
    if (preference instanceof EditTextPreference)
        f = EditTextPreferenceDialogFragment.newInstance(preference.getKey());
    ...
    f.show(getFragmentManager(), DIALOG_FRAGMENT_TAG);
}

Android.support.v7.preference.DialogPreferenceをサブクラス化し、onDisplayPreferenceDialogに同様のコードを使用してダミーのFontPreferenceFragmentをインスタンス化してみましたが、次の例外で失敗します。

Java.lang.IllegalStateException: Target fragment must implement TargetFragment interface

この時点で、私はすでに混乱の奥深くにいるので、これ以上掘り下げたくありません。 Googleはこの例外について何も知りません。とにかく、この方法は複雑すぎるようです。では、Android.support.v7.preferenceライブラリを使用してカスタム設定を作成する最良の方法は何ですか?

23
squirrel

重要な注意:現在(v7ライブラリのv23.0.1)、 'PreferenceThemeOverlay'で多くのテーマの問題がまだあります( この問題 )。たとえばLollipopでは、Holoスタイルのカテゴリヘッダーが作成されます。

苛立たしい数時間の後、私はついにカスタムv7プリファレンスを作成することに成功しました。独自のPreferenceを作成することは、必要と考えるよりも難しいようです。時間がかかることを確認してください。

最初は、なぜ各優先タイプにDialogPreferencePreferenceDialogFragmentCompatの両方が見つかるのか疑問に思われるかもしれません。結局のところ、1つ目は実際の設定で、2つ目は設定が表示されるDialogFragmentです。残念ながら、サブクラスboth そのうちの。

心配しないでください。コードを変更する必要はありません。いくつかのメソッドを再配置する必要があるだけです:

  • すべての設定編集メソッド(setTitle()またはpersist*()など)はDialogPreferenceクラスにあります。
  • すべてのダイアログ(-editing)メソッド(onBindDialogView(View)onDialogClosed(boolean))はPreferenceDialogFragmentCompatに移動されました。

あなたはあなたが既存のクラスを最初のものを拡張したいと思うかもしれません、そうすればあなたは私が思うに多くを変える必要がないのです。オートコンプリートは、不足しているメソッドを見つけるのに役立ちます。

上記の手順が完了したら、これらの2つのクラスを一緒にバインドします。 xmlファイルでは、preference-partを参照します。ただし、Androidは、カスタム設定が必要なときにどのFragmentを膨らませる必要があるかをまだ認識していません。そのため、onDisplayPreferenceDialog(Preference)をオーバーライドする必要があります:

@Override
public void onDisplayPreferenceDialog(Preference preference) {
    DialogFragment fragment;
    if (preference instanceof LocationChooserDialog) {
        fragment = LocationChooserFragmentCompat.newInstance(preference);
        fragment.setTargetFragment(this, 0);
        fragment.show(getFragmentManager(),
                "Android.support.v7.preference.PreferenceFragment.DIALOG");
    } else super.onDisplayPreferenceDialog(preference);
}

また、DialogFragmentは「キー」を処理する必要があります。

public static YourPreferenceDialogFragmentCompat newInstance(Preference preference) {
    YourPreferenceDialogFragmentCompat fragment = new YourPreferenceDialogFragmentCompat();
    Bundle bundle = new Bundle(1);
    bundle.putString("key", preference.getKey());
    fragment.setArguments(bundle);
    return fragment;
}

これでうまくいくはずです。問題が発生した場合は、既存のサブクラスを調べて、Androidがどのように解決したかを確認してください(Android Studio:クラスの名前を入力してCtrl + b逆コンパイルされたクラスを表示します。

40
Coen B

Support Preferenceライブラリを拡張するカスタム設定クラスを作成する方法を詳細に説明する優れたチュートリアルとGithubプロジェクトがあります。

重要な点は次のとおりです。

  • 設定行がクリックされたときのダイアログの起動を制御するカスタムPreferenceDialogFragmentCompatが必要になります。また、onBindDialogView()でダイアログのビューを構成します。

  • 設定画面で、onDisplayPreferenceDialog()をオーバーライドして、カスタムPreferenceDialogFragmentCompatを起動します。

  • ダイアログレイアウトを含むカスタムDialogPreferenceが必要になります。このDialogPreferenceをXML設定ファイルに追加します。

0
Mr-IDE

例外は、FontPreferenceFragmentDialogPreference.TargetFragment を実装していない場合に発生します。フラグメントがそのインターフェースを実装していることを確認する必要があります。

0
ianhanniballake