2012-04-05 9 views
6

Ho bisogno di voci dinamiche in ListPreference, quindi non posso usare il metodo convenzionale di configurazione XML di cui ci sono tonnellate di materiali online. Finora ho seguito la configurazione come puoi vedere qui sotto. Il problema è che quando eseguo questo vedo la finestra di dialogo con il titolo e il messaggio ma non vengono mostrate le voci anche se so che le voci e i valori non sono vuoti (so che le mie voci e valori sono gli stessi ma otterrei un errore se non lo facessi voci in dotazione)Elenco personalizzato Riferimento con voci dinamiche


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

risposta

14

Android: dialogMessage è stato un buon punto di partenza, grazie @MH. per individuarlo. Bellow è semplice messa a punto ho finito con, spero che qualcuno potrebbe trovare utile

<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

È questo l'unico modo per riempire il 'ListPreference' in modo programmatico? – enzom83

+0

@ enzom83 questa è l'idea di base su come farlo. Non pretendo di essere il migliore, ma per quanto tu possa vedere non ci sono stati altri post in merito. Stai avendo dei problemi? –

+1

@peter_budo: Non è necessario estendere ListPreference, è sufficiente impostare alcuni valori iniziali in 'onCreate()' e quindi sovrascrivere il gestore 'onPreferenceClick()' per l'oggetto specifico. Ecco un esempio: http://stackoverflow.com/questions/6474707/how-to-fill-listpreference-dynamically-when-onpreferenceclick-is-triggered – ccpizza

3

posso vedere alcuni potenziali possibilità di perché non sta funzionando come previsto:

  1. dove viene listObjects vengono? La sua presenza suggerisce che è una variabile membro, ma non la vedo settata o inizializzata da nessuna parte. Verifica di non utilizzare un elenco "vuoto" per compilare la finestra di dialogo, in quanto ciò potrebbe causare l'assenza di elementi in esso contenuti.

  2. In alternativa, stai sempre chiamando esplicitamente setEntries(...)esetEntryValues(...)? Sto chiedendo, perché ListPreference non utilizza questi due setter internamente: utilizza direttamente le variabili dei membri privati ​​(mEntries e mEntryValues). In altre parole, se non chiamate mai entrambe le funzioni da soli, nessuno lo farà, il che significa che gli array non verranno mai impostati sulla super classe; quindi il dialogo vuoto.

  3. Simile alla mia prima osservazione: che cos'è entries()? Si trova in onPrepareDialogBuilder, ma non sembra essere dichiarato da nessuna parte.

Forse è meglio iniziare ad aggiungere alcuni frammenti di codice più, perché in base a tutto ciò che manca, non c'è modo di dire dove l'esatta origine del problema risiede ...

Edit: Va bene , Ho creato un rapido progetto di test per seguire i tuoi passi. La soluzione al tuo problema è in realtà abbastanza semplice: elimina l'attributo android:dialogMessage e gli elementi della tua lista dovrebbero apparire - Devo aggiungere che l'ho provato solo con un semplice ListPreference.

Il problema si trova facilmente se si guarda la fonte per ListPreference, con estensioni da DialogPreference. Nel ShowDialog() quanto segue può essere trovato:

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

Ora, come si può vedere tutto dipende da ciò che onCreateDialog ritorni, perché al momento onPrepareDialogBuilder si chiama, la decisione di cosa visualizzare è già fatta. Quindi cerchiamo di avere uno sguardo a che:

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 } 

Sembra tenta di gonfiare una risorsa a cui fa riferimento mDialogLayoutResId. Se non è impostato o disponibile, restituirà null e solo allora verrà visualizzato il messaggio 'messaggio'. Il contenuto (elenco con elementi) verrà visualizzato solo se è presente un riferimento valido. Se si desidera visualizzare sia il contenuto che il messaggio, sarà necessario aggiungere un layout di dialogo personalizzato utilizzando l'attributo android:dialogLayout e aggiungere un TextView con ID android:id="@android:id/message" come id. Nel caso di un numero ListPreference, il messaggio verrà mostrato sotto l'elenco, per impostazione predefinita.

Nota che è necessario non necessario estendere il ListPreference incorporato per aggiungere voci e valori a livello di codice. Chiamata semplice setEntries(...) e setEntryValues(...) sull'istanza ListPreference con i dati che si desidera visualizzare.

Inoltre, nel caso della sottoclasse DynamicPreference, qualsiasi comportamento modificato può essere ignorato quando si chiama super.onPrepareDialogBuilder(builder) completamente alla fine del metodo. Come accennato in precedenza però: ho appena provato questo con il valore predefinito ListPreference e sembra funzionare bene e fare tutto ciò che si richiede.

+0

1) Parte del codice che non ho postato, ma vi posso assicurare che non allineamento di ritorno, previsto. 2) No, non chiamarli da nessuna parte, sembra che io possa fraintendere il loro uso. 3) Come nel primo caso, parte del codice che non ho pubblicato e di nuovo restituisce l'oggetto valido –

+0

Si prega di dare un'occhiata alla modifica nella mia risposta sia per la causa del problema che per la soluzione. Si scopre che non è necessario sottoclasse 'ListPreference'. :) –

+0

Sì, funziona senza quell'attributo. Altre classi che estendono DialogPreference I finora utilizzate non hanno avuto problemi con esso. Ho fatto una piccola ricerca e sembra che l'attributo xml android: dialogMessage per ListPreference sia nell'elenco dei bug di Android http://code.google.com/p/android/issues/detail?id=4497 –