2012-04-05 10 views
6

Necesito entradas dinámicas en ListPreference, así que no puedo usar la forma convencional de configuración XML de la que hay toneladas de materiales en línea. Hasta ahora tengo la siguiente configuración como puedes ver a continuación. El problema es que cuando ejecuto esto veo el diálogo con el título y el mensaje, pero no se muestran las entradas, aunque sé que las entradas y los valores no están vacíos (sé que mis entradas y valores son los mismos, pero obtendría un error si no lo hiciera entradas suministrado)Lista personalizadaPreferencia con entradas dinámicas


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

Respuesta

14

El android: dialogMessage fue un buen punto de partida aquí, gracias @MH. para detectarlo. Abajo es simple configuración que terminó con, espero que alguien puede encontrar útil

<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

¿Es esta la única manera de llenar el 'ListPreference' de forma programática? – enzom83

+0

@ enzom83 esta es una idea básica de cómo hacerlo. No pretendo ser el mejor, pero hasta ahora puede ver que no ha habido otros mensajes al respecto. ¿Estás teniendo problemas? –

+1

@peter_budo: no es necesario extender ListPreference, es suficiente establecer algunos valores iniciales en 'onCreate()' y luego anular el manejador 'onPreferenceClick()' para el objeto específico. Aquí hay un ejemplo: http://stackoverflow.com/questions/6474707/how-to-fill-listpreference-dynamically-when-onpreferenceclick-is-triggered – ccpizza

3

puedo ver algunas posibilidades potenciales de por qué no está funcionando como se esperaba:

  1. dónde viene listObjects viene? Su presencia sugiere que es una variable miembro, pero no veo que se configure o inicialice en ningún lado. Verifique que no esté usando una lista 'vacía' para completar el diálogo, ya que podría estar causando la ausencia de elementos en él.

  2. Alternativamente, estás cada vez que llama explícitamente setEntries(...) y setEntryValues(...)? Estoy preguntando, porque ListPreference no usa esos dos setters internamente - usa directamente las variables de miembros privados (mEntries y mEntryValues) para eso. En otras palabras, si nunca llama a ambas funciones usted mismo, nadie lo hará, lo que significa que las matrices nunca se establecerán en la súper clase; de ahí el diálogo vacío.

  3. Similar a mi primera observación: ¿qué es entries()? Está sentado en onPrepareDialogBuilder, pero no parece ser declarado en ningún lado.

Tal vez lo mejor es empezar a añadir algunos más fragmentos de código, porque se basa en todo lo que le falta, no hay forma de saber que el origen exacto de su problema radica ...

Editar: Alright , Configuré un proyecto de prueba rápido para seguir tus pasos. La solución a su problema es bastante sencilla: deshágase del atributo android:dialogMessage, y los elementos de su lista deberían aparecer. Debo agregar que solo probé esto con un simple ListPreference.

El problema se encuentra fácilmente si nos fijamos en la fuente de ListPreference, con se extiende desde DialogPreference. En la siguiente ShowDialog() se puede encontrar:

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

Ahora, como se puede ver que todo depende de lo que onCreateDialog rendimientos, porque en el momento que se llama onPrepareDialogBuilder, la decisión de lo que desea mostrar ya está hecho. Así que vamos a echar un vistazo a eso:

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 } 

Parece que intenta inflar un recurso referenciado por mDialogLayoutResId. Si eso no está configurado o no está disponible, devolverá null y solo aparecerá el 'mensaje' de diálogo. El contenido (lista con elementos) solo se mostrará si se hace referencia a un diseño válido. Si desea mostrar tanto el contenido como el mensaje, deberá agregar un diseño de diálogo personalizado utilizando el atributo android:dialogLayout y agregar un TextView con android:id="@android:id/message" como id. En el caso de ListPreference, el mensaje se mostrará debajo de la lista, por defecto.

Tenga en cuenta que no necesita ampliar el ListPreference incorporado para agregar entradas y valores mediante programación. Llame simple setEntries(...) y setEntryValues(...) en la instancia ListPreference con los datos que desea que se muestre.

Además, en el caso de su DynamicPreference subclase, cualquier comportamiento ha cambiado puedan quedar anulado como se llama a super.onPrepareDialogBuilder(builder) todo el camino al final de su método. Como mencioné anteriormente: acabo de probar esto con el predeterminado ListPreference y parece funcionar bien y hacer todo lo que solicite.

+0

1) Parte del código que no me fijé, pero puedo asegurarles que no return array como se esperaba. 2) No, no llamándolos a ninguna parte, parece que puedo malinterpretar su uso. 3) Como en el primer caso, parte del código que no publiqué y nuevamente devuelve el objeto válido –

+0

Mire la edición en mi respuesta tanto por la causa de su problema como por la solución. Resulta que no necesita subclasificar 'ListPreference'. :) –

+0

Sí, esto funciona sin ese atributo. Otras clases que extendieron DialogPreference I hasta ahora no tuvieron ningún problema. Hice una pequeña búsqueda y parece que el atributo xml android: dialogMessage para ListPreference está en la lista de errores de Android http://code.google.com/p/android/issues/detail?id=4497 –

Cuestiones relacionadas