7

ListPreference に動的なエントリが必要なため、オンラインに大量の資料がある従来の XML 設定方法を使用できません。これまでのところ、以下に示すように次のセットアップがあります。問題は、これを実行すると、タイトルとメッセージを含むダイアログが表示されますが、エントリと値が空ではないことを知っていてもエントリが表示されないことです (エントリと値が同じであることはわかっていますが、そうでない場合はエラーが発生します)提供されたエントリ)


my.preference.DynamicPreference
            android:title="@string/date_format"
            android:dialogMessage="@string/profile_info_date_format"
            android:entryValues="@array/date_format_values"
            android:entries="@array/date_format_values"

public class DynamicPreference extends ListPreference {
    private int index;

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

    public DynamicPreference(Context context) {
        super(context);
    }

    @Override
    protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
        builder.setTitle(getTitle());
        builder.setMessage(getDialogMessage());
        builder.setSingleChoiceItems(entries(), -1, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {

            }
        });
        super.onPrepareDialogBuilder(builder);
    }

    @Override
    public void setEntries(CharSequence[] sequence) {
        CharSequence[] entries = listObjects().toArray(new CharSequence[listObjects().size()]);
        super.setEntries(entries);
    }

    @Override
    public void setEntryValues(CharSequence[] sequence) {
        CharSequence[] values = getContext().getResources().getStringArray(R.string.date_format);
        super.setEntryValues(values);
    }
}
4

2 に答える 2

14

android:dialogMessage は良い出発点でした。@MH に感謝します。それを見つけるために。以下は私が終了した簡単なセットアップです。誰かが参考になることを願っています

<my.preference.DynamicPreference
        android:title="@string/local_time"
        android:key="profile_info_local_time"
        />

public class DynamicPreference extends ListPreference {


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

    public DynamicPreference(Context context) {
        super(context);
    }

    @Override
    protected View onCreateDialogView() {
        ListView view = new ListView(getContext());
        view.setAdapter(adapter());
        setEntries(entries());
        setEntryValues(entryValues());
        setValueIndex(initializeIndex());
        return view;
    }

    private ListAdapter adapter() {
        return new ArrayAdapter(getContext(), android.R.layout.select_dialog_singlechoice);
    }

    private CharSequence[] entries() {
        //action to provide entry data in char sequence array for list
    }

    private CharSequence[] entryValues() {
        //action to provide value data for list
    }
}
于 2012-04-12T09:43:26.103 に答える
3

期待どおりに機能しない理由について、いくつかの潜在的な可能性を確認できます。

  1. どこlistObjectsから来たの?その存在は、それがメンバー変数であることを示唆していますが、どこにも設定または初期化されていません。「空の」リストを使用してダイアログにデータを入力していないことを確認してください。ダイアログにアイテムが存在しない原因となっている可能性があります。

  2. または、明示的に呼び出していることはsetEntries(...) あり setEntryValues(...)ますか?ListPreference はこれら 2 つのセッターを内部的に使用しないため、私は尋ねています。そのためにプライベート メンバー変数 (mEntriesおよびmEntryValues) を直接使用します。つまり、両方の関数を自分で呼び出さない限り、誰も呼び出さないということです。つまり、スーパー クラスでも配列が設定されることはありません。したがって、空のダイアログです。

  3. 私の最初の観察に似ています: とは何entries()ですか? に座っていonPrepareDialogBuilderますが、どこにも宣言されていないようです。

欠落しているすべてのものに基づいて、問題の正確な原因がどこにあるのかを知る方法がないため、コードスニペットを追加し始めるのがおそらく最善です...

編集:さて、私はあなたの手順に従うために簡単なテストプロジェクトをセットアップしました. 問題の解決策は実際にはかなり簡単です。属性を取り除くandroid:dialogMessageと、リスト項目が表示されるはずです-これをプレーンでのみテストしたことを追加する必要がありますListPreference

ListPreferenceこの問題は、 extends fromのソースを見れば簡単に見つかりますDialogPreference。以下ShowDialog()で見つけることができます:

285        View contentView = onCreateDialogView();
286        if (contentView != null) {
287            onBindDialogView(contentView);
288            mBuilder.setView(contentView);
289        } else {
290            mBuilder.setMessage(mDialogMessage);
291        }
292        
293        onPrepareDialogBuilder(mBuilder);

ご覧のとおり、すべて onCreateDialog が返す内容に依存します。これは、onPrepareDialogBuilderが呼び出された時点で、何を表示するかがすでに決定されているためです。それでは、それを見てみましょう:

336    protected View onCreateDialogView() {
337        if (mDialogLayoutResId == 0) {
338            return null;
339        }
340        
341        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
342                Context.LAYOUT_INFLATER_SERVICE);
343        return inflater.inflate(mDialogLayoutResId, null);
344    }

によって参照されるリソースを膨張させようとしているようmDialogLayoutResIdです。それが設定されていないか利用できない場合は、戻りnull、ダイアログの「メッセージ」が表示されます。コンテンツ (アイテムのリスト) は、有効なレイアウトが参照されている場合にのみ表示されます。android:dialogLayoutコンテンツとメッセージの両方を表示する場合は、属性を使用してカスタム ダイアログ レイアウトを追加し、TextViewwith android:id="@android:id/message"as idを追加する必要があります。の場合ListPreference、メッセージはデフォルトでリストの下に表示されます。

プログラムでエントリと値を追加するために、組み込みの ListPreference を拡張する必要はないことに注意してください。単純な呼び出しsetEntries(...)setEntryValues(...)、表示するデータを含む ListPreference インスタンスで。

また、サブクラスの場合、メソッドの最後でずっとDynamicPreference呼び出すと、変更した動作がオーバーライドされる可能性があります。super.onPrepareDialogBuilder(builder)前述のように、私はこれをデフォルトでテストしたところ、ListPreference問題なく動作し、要求されたすべてのことを行うようです。

于 2012-04-05T21:22:50.243 に答える