2012-06-25 23 views
18

Tengo que crear una vista personalizada más compleja en Android. La disposición final debe tener este aspecto:Android: Vista múltiple de niños para vista personalizada con diseño existente

<RelativeLayout> 
    <SomeView /> 
    <SomeOtherView /> 
    <!-- maybe more layout stuff here later --> 
    <LinearLayout> 
    <!-- the children --> 
    </LinearLayout> 
</RelativeLayout> 

Sin embargo, en los archivos XML sólo quiero no definir este (sin definir SomeView, SomeOtherView etc.):

<MyCustomView> 
    <!-- the children --> 
</MyCustomView> 

Es esto posible en Android, y si es así: ¿cuál sería la forma más limpia de hacerlo? Las posibles soluciones que se me ocurrieron fueron 'anular los métodos addView()' y 'eliminar todas las vistas y agregarlas más tarde', pero no estoy seguro de qué camino tomar ...

Muchas gracias de antemano ¡para su ayuda! :)

Respuesta

34

Es absolutamente posible, y recomendado, crear vistas personalizadas de contenedor. Esto es lo que Android llamaría un control compuesto. Por lo tanto:

public class MyCustomView extends RelativeLayout { 
    private LinearLayout mContentView; 

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

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

    public MyCustomView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     //Inflate and attach your child XML 
     LayoutInflater.from(context).inflate(R.layout.custom_layout, this); 
     //Get a reference to the layout where you want children to be placed 
     mContentView = (LinearLayout) findViewById(R.id.content); 

     //Do any more custom init you would like to access children and do setup 
    } 

    @Override 
    public void addView(View child, int index, ViewGroup.LayoutParams params) { 
     if(mContentView == null){ 
      super.addView(child, index, params); 
     } else { 
      //Forward these calls to the content view 
      mContentView.addView(child, index, params); 
     } 
    } 
} 

Puede anular tantas versiones de addView() como se sienta son necesarios, pero al final todos ellos llamada de vuelta a la versión que se coloca en la muestra. Al anular solo este método, el marco pasará todos los elementos secundarios encontrados dentro de su etiqueta XML a un contenedor secundario específico.

Y luego modificar el XML como por ejemplo:

res/layout/custom_layout.xml

<merge> 
    <SomeView /> 
    <SomeOtherView /> 
    <!-- maybe more layout stuff here later --> 
    <LinearLayout 
     android:id="@+id/content" /> 
</merge> 

La razón para usar <merge> es simplificar la jerarquía. Todas las vistas secundarias se adjuntarán a su clase personalizada, que es RelativeLayout. Si no usa <merge>, termina con un RelativeLayout adjunto a otro RelativeLayout adjunto a todos los elementos secundarios, que puede causar problemas.

HTH

+0

la solución, porque dije: quiero definir a los niños en otros lugares (no en la vista personalizada). Más exactamente: tengo archivos de diseño a.xml, b.xml, c.xml, todos con la misma vista personalizada, pero con diferentes elementos secundarios en LinearLayout. – mreichelt

+0

Eso también es perfectamente aceptable, y yo diría que el método más fácil sería anular 'addView()' como describió. Edité el ejemplo de arriba. – Devunwired

+0

¡Gracias! Es bueno ver que estos problemas se resuelven incluso después de tanto tiempo. :) – mreichelt

-3

puede utilizar etiqueta include

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> 
    <include android:id="@+id/nav_bar_layout" layout="@layout/nav_bar" android:layout_above="@+id/web_view" /> 
    <WebView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/web_view" android:layout_centerInParent="true" /> 
    <include android:id="@+id/admob_layout" layout="@layout/admob_layout" android:layout_below="@+id/web_view" /> 
</RelativeLayout> 
No
+1

Ya escribí que no quiero definir (ni incluir) las vistas cada vez que uso mi vista personalizada, porque en última instancia pertenecen _ a la vista personalizada. – mreichelt

Cuestiones relacionadas