2011-04-22 5 views
18

Tengo un par de implementaciones personalizadas DialogPreference que flotan alrededor, como this one:Preferencia personalizada, targetSdkVersion = "11": ¿sangría faltante?

package apt.tutorial; 

import android.content.Context; 
import android.content.res.TypedArray; 
import android.os.Bundle; 
import android.os.Parcel; 
import android.os.Parcelable; 
import android.preference.DialogPreference; 
import android.util.AttributeSet; 
import android.view.View; 
import android.view.ViewGroup; 
import android.view.ViewParent; 
import android.widget.TimePicker; 

public class TimePreference extends DialogPreference { 
    private int lastHour=0; 
    private int lastMinute=0; 
    private TimePicker picker=null; 

    public static int getHour(String time) { 
     String[] pieces=time.split(":"); 

     return(Integer.parseInt(pieces[0])); 
    } 

    public static int getMinute(String time) { 
     String[] pieces=time.split(":"); 

     return(Integer.parseInt(pieces[1])); 
    } 

    public TimePreference(Context ctxt) { 
     this(ctxt, null); 
    } 

    public TimePreference(Context ctxt, AttributeSet attrs) { 
     this(ctxt, attrs, 0); 
    } 

    public TimePreference(Context ctxt, AttributeSet attrs, int defStyle) { 
     super(ctxt, attrs, defStyle); 

     setPositiveButtonText("Set"); 
     setNegativeButtonText("Cancel"); 
    } 

    @Override 
    protected View onCreateDialogView() { 
     picker=new TimePicker(getContext()); 

     return(picker); 
    } 

    @Override 
    protected void onBindDialogView(View v) { 
     super.onBindDialogView(v); 

     picker.setCurrentHour(lastHour); 
     picker.setCurrentMinute(lastMinute); 
    } 

    @Override 
    protected void onDialogClosed(boolean positiveResult) { 
     super.onDialogClosed(positiveResult); 

     if (positiveResult) { 
      lastHour=picker.getCurrentHour(); 
      lastMinute=picker.getCurrentMinute(); 

      String time=String.valueOf(lastHour)+":"+String.valueOf(lastMinute); 

      if (callChangeListener(time)) { 
       persistString(time); 
      } 
     } 
    } 

    @Override 
    protected Object onGetDefaultValue(TypedArray a, int index) { 
     return(a.getString(index)); 
    } 

    @Override 
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { 
     String time=null; 

     if (restoreValue) { 
      if (defaultValue==null) { 
       time=getPersistedString("00:00"); 
      } 
      else { 
       time=getPersistedString(defaultValue.toString()); 
      } 
     } 
     else { 
      time=defaultValue.toString(); 
     } 

     lastHour=getHour(time); 
     lastMinute=getMinute(time); 
    } 
} 

Ellos trabajan muy bien. Sin embargo, en una aplicación con android:targetSdkVersion="11" definido, en un XOOM, muestran perdiendo el guión cuando en el PreferenceActivity:

PreferenceActivity with messed-up custom DialogPreference

Además, el tamaño de la fuente aparece una pizca más grande, al menos por el título.

No hay nada en DialogPreference donde realmente estoy anulando cualquier comportamiento de formato para esas cosas, AFAIK. El XML preferencia es nada especial, aparte de referirse a la clase anterior:

<PreferenceScreen 
    xmlns:android="http://schemas.android.com/apk/res/android"> 
    <ListPreference 
     android:key="sort_order" 
     android:title="Sort Order" 
     android:summary="Choose the order the list uses" 
     android:entries="@array/sort_names" 
     android:entryValues="@array/sort_clauses" 
     android:dialogTitle="Choose a sort order" /> 
    <CheckBoxPreference 
     android:key="alarm" 
     android:title="Sound a Lunch Alarm" 
     android:summary="Check if you want to know when it is time for lunch" /> 
    <apt.tutorial.TimePreference 
     android:key="alarm_time" 
     android:title="Lunch Alarm Time" 
     android:defaultValue="12:00" 
     android:summary="Set your desired time for the lunch alarm" 
     android:dependency="alarm" /> 
    <CheckBoxPreference 
     android:key="use_notification" 
     android:title="Use a Notification" 
     android:defaultValue="true" 
     android:summary="Check if you want a status bar icon at lunchtime, or uncheck for a full-screen notice" 
     android:dependency="alarm" /> 
</PreferenceScreen> 

Alguien sabe dónde voy mal?

Gracias!


ACTUALIZACIÓN

Here is a link to a project que contiene esta preferencia costumbre y un simple archivo XML de preferencias que demuestra el problema. Incluso con solo dos clases de Java, XML de preferencia y un archivo arrays.xml, obtengo este fenómeno. Here is a compiled APK de este proyecto.

+0

Hay que ir a pedir la marca Murphy - lo sabe todo :) – JohnnyLambada

+1

@JohnnyLambada: lo he intentado, pero la oficina principal Green Bay Packers se negó a comentar. Oh espera. ¿No quisiste decir http://goo.gl/KNYOu? :-) – CommonsWare

+0

Siempre es bueno tener el mismo problema que Mark Murphy. Si no puede resolverlo fácilmente, entonces no me siento tan mal. – Intrications

Respuesta

12

(publicación cruzada de la associated android-developers thread)

bien, lo he descubierto.

Hay tres posibles constructores en una preferencia:

MyPreference(Context ctxt) 
MyPreference(Context ctxt, AttributeSet attrs) 
MyPreference(Context ctxt, AttributeSet attrs, int defStyle) 

En algún lugar a lo largo de la línea, cogí el patrón de tener la cadena constructor un parámetro al constructor de dos parámetros (pasando null para el 2do parámetro), y tener la cadena de constructor de dos parámetros en el constructor de tres parámetros (pasando 0 para el 3er parámetro).

Y esa no es la respuesta correcta.

Estoy esperando que la respuesta correcta es sólo para poner en práctica la segunda constructor, porque el estilo predeterminado correcto es interno a Android (com.android.internal.R.attr.dialogPreferenceStyle). El segundo constructor es el que se usa para inflar XML de preferencia.

¡Gracias a todos por la ayuda!

+0

¿La solución es simplemente poner "com.android.internal.R.attr.dialogPreferenceStyle" en lugar de 0 como el tercer atributo que se pasa al tercer constructor? Tuve el mismo problema que hace un tiempo y finalmente me rendí. – Tenfour04

+0

@ TenFour04: no tiene acceso a 'com.android.internal.R.attr.dialogPreferenceStyle'. – CommonsWare

+0

Bueno, eso no es divertido. No entiendo por qué ciertos recursos están restringidos y otros no. Por ejemplo, puede usar list_selector_background, pero no list_selector_holo_dark. Gracias. – Tenfour04

1

Probé tu código en el emulador. No hay problema con el código que ha dado, y todas las líneas tienen el mismo formato; pero todos se ven más similares (en formato) a la tercera preferencia (Lunch Alarm Time) que los demás.

Parece que las otras tres preferencias se sangran más de lo necesario. Por lo tanto, tal vez tenga algún estilo de formato global que se use, pero no se recoja en la preferencia TimePreference.

EDIT: OK. Entonces, lo anterior no es (completamente) verdad. Definitivamente hay un problema cuando probé con el SDK de destino establecido en HoneyComb. Pero al configurar el tema para la clase PreferenceActivity como android:theme="@android:style/Theme.Black", hay una consistencia en el aspecto de todas las preferencias, como se muestra a continuación.

enter image description here

Este estilo es similar a Froyo, pero no el HoneyComb; en este último, la fuente del título es más pequeña y hay más indentación. Probablemente, el tema predeterminado no esté asignado al Custom Preferences - solo una suposición :) Una solución alternativa sería asignar el tema predeterminado a su actividad de preferencia explícitamente, pero no sé cuál es el tema predeterminado en HoneyComb (y si puede establecerse).

+0

@Rajath DSouza: Obtengo el mismo comportamiento en el emulador 3.0 que en el XOOM. ¿Qué emulador probaste? – CommonsWare

+0

Lo probé con el emulador de Android SDK con Target configurado en 'Android 3.0 (nivel de API 11)' y Skin en 'WXGA'. – rajath

+0

@Rajath DSouza: Qué completamente extraño. No tengo ningún estilo en este proyecto en particular, por lo que no parece ser la fuente del problema. Tendré que hacer más experimentos e intentar reducir el problema un poco. – CommonsWare

6

Se puede bailar con void Preference.setWidgetLayoutResource(int widgetLayoutResId) método, aunque yo prefiero anular View Preference.onCreateView(ViewGroup parent) método en mi clase de las preferencias personalizadas y entrar ilegalmente en él mediante la adición de vistas personalizadas justo debajo de @android:id/summary (hierarchyviewer usar utilidad para más detalles).

El método completo es: Código

@Override 
protected View onCreateView(ViewGroup parent) 
{ 
    View ret = super.onCreateView(parent); 

    View summary = ret.findViewById(android.R.id.summary); 
    if (summary != null) 
    { 
     ViewParent summaryParent = summary.getParent(); 
     if (summaryParent instanceof ViewGroup) 
     { 
      final LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      ViewGroup summaryParent2 = (ViewGroup) summaryParent; 
      layoutInflater.inflate(R.layout.seek_bar_preference, summaryParent2); 

      seekBar = (SeekBar) summaryParent2.findViewById(R.id.seekBar); 
      seekBar.setMax(maxValue - minValue); 
      seekBar.setOnSeekBarChangeListener(this); 

      statusText = (TextView) summaryParent2.findViewById(R.id.seekBarPrefValue); 

      unitsRightView = (TextView) summaryParent2.findViewById(R.id.seekBarPrefUnitsRight); 
      unitsLeftView = (TextView) summaryParent2.findViewById(R.id.seekBarPrefUnitsLeft); 
     } 
    } 

    return ret; 
} 

Fuente de mi clase SeekBarPreference basado en el código de http://robobunny.com se puede descargar here image1 image2

1

La solución que me ayudó:

I ha reemplazado

public TimePreference(Context ctxt, AttributeSet attrs) { 
    this(ctxt, attrs, 0); 
} 

con

public TimePreference(Context ctxt, AttributeSet attrs) { 
    this(ctxt, attrs, ctxt.getResources().getSystem().getIdentifier("dialogPreferenceStyle", "attr", "android")); 
} 

Como se puede ver, que sustituyen tercer argumento con ctxt.getResources() getSystem(). GetIdentifier ("dialogPreferenceStyle", "attr", "androide".) en el segundo constructor de clase de preferencia personalizada.

+0

Gracias. Me es de gran ayuda. – Dalinaum

1

Para que la respuesta aceptada sea más clara. Sólo necesita este constructor:

public TimePreference(Context ctxt, AttributeSet attrs) { 
    // this(ctxt, attrs, 0); // wrong 
    super(ctxt, attrs); 
} 
Cuestiones relacionadas