2010-05-21 39 views
32

estoy aprendiendo sobre el uso de vistas personalizadas de los siguientes:Android vista personalizada Constructor

http://developer.android.com/guide/topics/ui/custom-components.html#modifying

La descripción dice:

clase de inicialización Como siempre, el super se llama en primer lugar. Además, no es un constructor por defecto, sino parametrizado. EditText es creado con estos parámetros cuando está inflado desde un archivo de diseño XML, por lo tanto, nuestro constructor necesita ambos tómelos y páselos también al constructor de la superclase .

¿Hay una mejor descripción? He estado tratando de descubrir cómo deberían verse los constructores y he encontrado 4 opciones posibles (ver ejemplo al final de la publicación). No estoy seguro de lo que estas 4 opciones hacen (o no), por qué debería implementarlas o qué significan los parámetros. ¿Hay una descripción de estos?

public MyCustomView() 
{ 
    super(); 
} 

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

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

public MyCustomView(Context context, AttributeSet attrs, Map params) 
{ 
    super(context, attrs, params); 
} 
+0

Pregunta similar aquí: http://stackoverflow.com/questions/9195713/do-i-need-all-three-constructors-for-an-android-custom-view – mbonnin

Respuesta

61

No necesita la primera, ya que simplemente no funcionará.

El tercero significará que su personalizado View se podrá utilizar a partir de archivos de diseño XML. Si no te importa eso, no lo necesitas.

El cuarto es simplemente incorrecto, AFAIK. No hay un constructor View que tome un Map como el tercer parámetro. Hay uno que toma un int como el tercer parámetro, utilizado para anular el estilo predeterminado para el widget.

que tienden a utilizar la sintaxis this() combinar estas:

public ColorMixer(Context context) { 
    this(context, null); 
} 

public ColorMixer(Context context, AttributeSet attrs) { 
    this(context, attrs, 0); 
} 

public ColorMixer(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    // real work here 
} 

Se puede ver el resto de este código en this book example.

+7

super (context, attrs) y super (context, attrs, 0) funciona de manera diferente para mí. El primero está bien, pero el segundo elimina el estilo original de una vista. ¿Es un error en las versiones más recientes de Android? – broot

+9

Sí, mi enfoque 'this()' tenía defectos. Simplemente haga una cadena simple a la superclase (por ejemplo, 'super (context, attrs)') y realice una llamada a un método privado común (por ejemplo, 'init();') en cada constructor. Consulte https://github.com/commonsguy/cwac-colormixer/blob/master/src/com/commonsware/cwac/colormixer/ColorMixer.java para ver un ejemplo. – CommonsWare

+0

Sí, hice exactamente lo mismo, pero llamé esto (contexto, nulo) en el primer constructor. Una falla es que tienes que inicializar los campos finales en ambos constructores; no puedes hacer eso en el método init(). – broot

11

He aquí una mi patrón (la creación de una costumbre ViewGoup aquí, pero aún así):

// CustomView.java 

public class CustomView extends LinearLayout { 

    public CustomView(Context context) { 
     super(context); 
     init(context); 
    } 

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

    public CustomView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(context); 
    } 

    private void init(Context ctx) { 
     LayoutInflater.from(ctx).inflate(R.layout.view_custom, this, true); 
      // extra init 
    } 

} 

y

// view_custom.xml 

<merge xmlns:android="http://schemas.android.com/apk/res/android"> 
    <!-- Views --> 
</merge> 
+0

Esto no es tan efectivo como la solución @CommonsWare porque no le permite tener campos marcados como 'final', mientras que usar una cadena de this() llamará a. – greg7gkb

+3

@ greg7gkb Sin embargo, la solución de @Commonsware es defectuosa. Debe llamar a cada super por separado y usar 'init()' – Blundell

+0

. No es necesario pasar Contexto a init(), solo puede llamar a getContext() – Ran

6

Cuando se agregan a su costumbre View de xml como:

<com.mypack.MyView 
     ... 
     /> 

necesitará public constructorMyView(Context context, AttributeSet attrs), de lo contrario obtendrá Exception cuando Android intente inflate su View.

Y cuando se agrega su View de xml y también especifique la android:styleattribute como:

<com.mypack.MyView 
     style="@styles/MyCustomStyle" 
     ... 
     /> 

también tendrá la tercera constructor públicoMyView(Context context, AttributeSet attrs,int defStyle).

El tercer constructor se utiliza por lo general al ampliar un estilo y personalizarlo, y luego que le gustaría establecer que style a un determinado View en sus diseños

Editar detalles

public MyView(Context context, AttributeSet attrs) { 
      //Called by Android if <com.mypack.MyView/> is in layout xml file without style attribute. 
      //So we need to call MyView(Context context, AttributeSet attrs, int defStyle) 
      // with R.attr.customViewStyle. Thus R.attr.customViewStyle is default style for MyView. 
      this(context, attrs, R.attr.customViewStyle); 
    } 

See this

+0

Tengo pocas vistas personalizadas en el mismo diseño. ¿Cómo puedo pasarle al constructor un índice que le dice a cuál de las vistas personalizadas pertenece? – Zvi

+0

Debería leer TypedArray y atributos de estilo. http://stackoverflow.com/questions/11039829/how-to-pass-view-reference-to-android-custom-view – Nepster

+0

@Nepstar, leí esa publicación y no entendí cómo va a resolver mi problema, porque los atributos estiloables, por lo que yo entiendo, son propiedades estáticas definidas antes de que se ejecute la aplicación. Por lo tanto, todas las instancias de mis componentes personalizados obtendrán los mismos datos, mientras que necesito una identificación única para cada uno que se ejecute. – Zvi

Cuestiones relacionadas