2012-04-05 28 views
6

Ich brauche dynamische Einträge in ListPreference, so kann ich nicht konventionelle Art der XML-Setup verwenden, von denen es Tonnen von Materialien online gibt. Bisher habe ich folgendes Setup, wie Sie unten sehen können. Problem ist, dass wenn ich dies ausführe ich Dialog mit Titel und Nachricht sehe, aber keine Einträge angezeigt werden, obwohl ich weiß, dass Einträge und Werte nicht leer sind (Ich weiß, dass meine Einträge und Werte identisch sind, aber ich würde Fehler erhalten, wenn ich nicht habe mitgelieferten Einträge)Benutzerdefinierte ListPreference mit dynamischen Einträgen


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); 
    } 
}

Antwort

14

Der Android: dialogMessage war guter Ausgangspunkt hier, danke @MH. um es zu entdecken. Bellow einfaches Setup, das ich mit endete, ich hoffe jemand hilfreich es

<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 
    } 
} 
+0

Ist dies die einzige Möglichkeit, die füllen 'ListPreference' auf programmatische Weise? – enzom83

+0

@ enzom83 das ist Grundidee, wie es geht. Ich behaupte nicht, der Beste zu sein, aber soweit Sie sehen können, gab es keine anderen Beiträge in Bezug darauf. Hast du Probleme? –

+1

@peter_budo: Es ist nicht notwendig, ListPreference zu erweitern, es ist ausreichend, einige Initialwerte in 'onCreate()' zu setzen und dann den 'onPreferenceClick()' Handler für das spezifische Objekt zu überschreiben. Hier ist ein Beispiel: http://stackoverflow.com/questions/6474707/how-to-fill-listpreference-dynamically-when-onpreferenceclick-is-triggered – ccpizza

3

ich einige potenzielle Möglichkeiten, warum sehen kann, ist es nicht wie erwartet funktioniert:

  1. Wo kommt listObjects kommen aus? Seine Anwesenheit legt nahe, dass es sich um eine Membervariable handelt, aber ich sehe nicht, dass sie irgendwo gesetzt oder initialisiert wird. Stellen Sie sicher, dass Sie keine "leere" Liste verwenden, um den Dialog zu füllen, da dies dazu führen kann, dass keine Elemente darin enthalten sind.

  2. Alternativ werden Sie jemals Aufruf explizit setEntries(...)undsetEntryValues(...)? Ich frage, weil ListPreference diese beiden Setter nicht intern verwendet - es verwendet direkt die privaten Member-Variablen (mEntries und mEntryValues) dafür. Mit anderen Worten, wenn Sie nicht beide Funktionen selbst aufrufen, wird niemand, was bedeutet, dass die Arrays auch nie auf der Super-Klasse gesetzt werden; daher der leere Dialog.

  3. Ähnlich meiner ersten Beobachtung: Was ist entries()? Es sitzt in onPrepareDialogBuilder, aber es scheint nirgends deklariert werden.

Vielleicht ist es am besten, das Hinzufügen einiger mehr Code-Schnipsel zu beginnen, weil sie auf alles aus, dass, fehlt es keine Möglichkeit gibt zu sagen, wo der genaue Ursprung des Problems liegt ...

Edit: Okay Ich habe ein schnelles Testprojekt eingerichtet, um deinen Schritten zu folgen. Die Lösung für Ihr Problem ist eigentlich ziemlich einfach: Entfernen Sie das Attribut android:dialogMessage, und Ihre Liste Elemente sollten angezeigt werden - ich muss hinzufügen, dass ich dies nur mit einer einfachen ListPreference getestet.

Das Problem ist leicht zu finden, wenn Sie die Quelle für betrachten, mit erstreckt sich von DialogPreference. In ShowDialog() kann folgendes finden:

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); 

Nun, wie Sie es hängt alles von sehen kann, was onCreateDialog zurückkehrt, weil zu der Zeit onPrepareDialogBuilder genannt wird, was die Entscheidung bereits angezeigt werden soll. Werfen wir also einen Blick auf, dass:

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 } 

Es scheint, er versucht, eine Ressource, die von mDialogLayoutResId verwiesen aufzublasen. Wenn das nicht festgelegt oder verfügbar ist, gibt es null zurück und nur dann wird der Dialog 'Nachricht' angezeigt. Der Inhalt (Liste mit Elementen) wird nur angezeigt, wenn ein gültiges Layout referenziert ist. Wenn sowohl der Inhalt als auch die Nachricht angezeigt werden sollen, müssen Sie ein benutzerdefiniertes Dialogfeldlayout mit dem Attribut android:dialogLayout hinzufügen und als ID TextView mit android:id="@android:id/message" hinzufügen. Im Fall einer wird die Nachricht standardmäßig unter der Liste angezeigt.

Beachten Sie, dass Sie nicht müssen die integrierte ListPreference erweitern, um Einträge und Werte programmgesteuert hinzufügen. Einfacher Aufruf setEntries(...) und setEntryValues(...) auf der ListPreference-Instanz mit den Daten, die Sie anzeigen möchten.

Auch im Falle Ihrer Unterklasse DynamicPreference kann jedes Verhalten, das Sie geändert haben, überschrieben werden, wenn Sie am Ende der Methode den ganzen Weg super.onPrepareDialogBuilder(builder) aufrufen. Wie bereits erwähnt: Ich habe das gerade mit dem Standard getestet und das scheint gut zu funktionieren und alles zu tun, was Sie verlangen.

+0

1) Ein Teil des Codes finden kann, die ich nicht geschrieben, aber ich kann Ihnen versichern, dass es Array zurückgibt, wie erwartet. 2) Nein, ich rufe sie nirgendwo an, scheint, dass ich sie missverstehen könnte. 3) Wie im ersten Fall ein Teil des Codes, den ich nicht gepostet habe und wieder gibt es gültiges Objekt zurück –

+0

Bitte werfen Sie einen Blick auf die Bearbeitung in meiner Antwort für die Ursache Ihres Problems und die Lösung. Es stellt sich heraus, dass Sie die 'ListPreference' nicht ableiten müssen. :) –

+0

Ja, das funktioniert ohne dieses Attribut. Andere Klassen, die bisher die DialogPreference I erweitert haben, hatten kein Problem damit. Ich habe kleine Suche und es scheint, dass XML-Attribut android: dialogMessage für ListPreference ist auf Android Bug-Liste http://code.google.com/p/android/issues/detail?id=4497 –

Verwandte Themen