2012-06-29 23 views
22

que hacer diseño complejo y el uso de "incluir" para mi componente personalizado, como esteIncluir diseño con atributos personalizados

<include layout="@layout/topbar"/> 

Y topbar define así:

<?xml version="1.0" encoding="utf-8"?> 
<my.package.TopBarLayout 
... a lot of code 

Ahora, quiero pase mis atributos definidos a la "barra superior" como este

<include layout="@layout/topbar" txt:trName="@string/contacts"/> 

Pero no tengo ningún resultado. Entendí desde that page que no puedo establecer ningún atributo, pero id, alto y ancho.

Entonces, ¿cómo puedo pasar mis atributos definidos personalizados para incluir, y cómo puedo hacer que funcione?

+0

[El enlace de datos no lo hace soporte incluido como hijo directo de un elemento de fusión.] (https://developer.android.com/topic/libraries/data-binding/index.html) – samosaris

Respuesta

31

Sé que esta es una pregunta anterior, pero la encontré y descubrí que ahora es posible gracias a la vinculación de datos.

Primero debe habilitar Data Binding en su proyecto.

A continuación, añadir que se unen a la disposición de los datos que desea incluir:

<?xml version="1.0" encoding="utf-8"?> 
<layout xmlns:android="http://schemas.android.com/apk/res/android"> 
<data> 
    <variable name="title" type="java.lang.String"/> 
</data> 
<RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto" 
      android:id="@+id/screen_header" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:layout_gravity="top" 
      android:gravity="center"> 

... 

<TextView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerInParent="true" 
      android:textSize="20sp" 
      android:textStyle="bold" 
      android:text="@{title}"/> 

... 

</RelativeLayout> 
</layout> 

Por último, pasar la variable de la disposición principal de la disposición incluida como esto:

... 
xmlns:app="http://schemas.android.com/apk/res-auto" 
... 
<include layout="@layout/included_layout" 
      android:id="@+id/title" 
      app:title="@{@string/title}"/> 
... 
+1

¿está funcionando? ¿cómo se puede vincular desde xml? Cuando intento esto, no había texto en el diseño incluido – Andrzej

+0

@Andrzej Me funciona, por lo que debe estar perdiendo algo, tal vez algo que olvidé agregar a mi respuesta. ¿Puedes publicar tu código así que intento descubrir qué está mal? –

+0

Esto funciona, pero de hecho lo hace dependiente del enlace de datos que puede ser más difícil de depurar que el enfoque de vista personalizado descrito en otra respuesta (que se basa más en las comprobaciones en tiempo de compilación) – sapht

0

Debe incluir en su elemento raíz xml su espacio de nombres personalizado. Si se com.example.test el nombre del paquete de su xml embestido, algo como esto:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:txt="http://schemas.android.com/apk/res/com.example.test" /> 

Un buen tutorial es: http://blog.infidian.com/2008/05/02/android-tutorial-42-passing-custom-variables-via-xml-resource-files/

+3

Gracias, pero lo sé, y el espacio de nombres está incluido. El problema es que los atributos no pasaron al componente –

5

Por desgracia, la única cosa que puedo aportar es que yo también era incapaz para establecer atributos personalizados en una etiqueta de inclusión, y hacer que pasen al diseño incluido.

Puede que no sea posible en este punto.

9

No es posible asignar atributos distintos a los parámetros de diseño, visibilidad o ID en una etiqueta de inclusión. Esto incluye atributos personalizados.

Usted puede verificar esto buscando en la fuente del método LayoutInflater.parseInclude, alrededor de la línea 705: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/view/LayoutInflater.java#640

El inflador sólo se aplica el ID y atributos de visibilidad a la disposición incluida.

0

Tenía la misma pregunta. Después de visitar este hilo, terminé usando los métodos ViewsetTag() para adjuntar información de identificación a cada View durante onCreate(), y luego a los métodos getTag() para recuperarlos más tarde.

7

I se encontró con este problema hoy. Por lo que sea que valga, creo que hay una solución directa. En lugar de agregar atributos a la etiqueta de inclusión, cree una vista de contenedor personalizada para incluir y agregar atributos a esa. Luego, haz la inclusión desde el contenedor. Haga que la implementación de la clase contenedora extraiga los atributos y los transfiera a su único elemento secundario, que es la vista raíz del diseño de inclusión.

Por lo tanto, decimos que declaramos algunos atributos personalizados para un envoltorio llamada SingleSettingWrapper como esto -

<declare-styleable name="SingleSettingWrapper"> 
    <attr name="labelText" format="string"/> 
</declare-styleable> 

Entonces, creamos dos clases de vista personalizada - una para la envoltura (SingleSettingWrapper) y uno para el niño (SingleSettingChild) que se incluirá -

<!-- You will never end up including this wrapper - it will be pasted where ever you wanted to include. But since the bulk of the XML is in the child, that's ok --> 
<com.something.SingleSettingWrapper 
    android:id="@+id/wrapper" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    custom:labelText="@string/my_label_string"> 

    <!-- Include the child layout --> 
    <include layout="@layout/setting_single_item"/> 

</com.something.SingleSettingWrapper> 

Para el niño, podemos poner cualquier distribución compleja que queramos. Voy a poner algo básico, pero en realidad se puede incluir cualquier cosa -

<com.something.SingleSettingItem 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical"> 
    <RelativeLayout > 
     <!-- add whatever custom stuff here --> 
     <!-- in this example there would be a text view for the label and maybe a bunch of other stuff --> 
     <!-- blah blah blah --> 
    </RelativeLayout> 
</com.something.SingleSettingItem> 

Para la envoltura (esta es la clave), leemos todos nuestros atributos personalizados en el constructor. Luego, anulamos ViewAdded() y pasamos esos atributos personalizados a nuestro hijo.

public class SingleSettingWrapper extends FrameLayout 
{ 
    private String mLabel; 

    public SingleSettingWrapper(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 

     TypedArray a = context.getTheme().obtainStyledAttributes(attrs, 
                  R.styleable.SingleSettingWrapper, 
                  0, 0); 

     mLabel = a.getString(R.styleable.SingleSettingWrapper_labelText); 
     a.recycle(); 
    } 

    public void onViewAdded(View child) 
    { 
     super.onViewAdded(child); 
     if (!(child instanceof SingleSettingItem)) 
      return; 

     ((TextView)child.findViewById(R.id.setting_single_label)).setText(mLabel); 
     /* 
     Or, alternatively, call a custom method on the child implementation - 
     ((SingleSettingItem)child)setLabel(mLabel); 
     */ 
    } 
} 

Opcionalmente, se puede aplicar también al niño y tienen que recibir los mensajes de la envoltura y modificar en sí (en lugar de tener la envoltura modificar el niño como lo hice anteriormente).

public class SingleSettingItem extends LinearLayout 
{ 
    public SingleSettingItem(Context context, AttributeSet attrs) 
    { 
     super(context, attrs); 
    } 

    public void setLabel(String l) 
    { 
     // set the string into the resource here if desired, for example 
    } 
} 

Al final del día, cada uno de los archivos XML donde quería <include> su diseño contendrá aproximadamente 7 líneas de XML para la envoltura + incluir en lugar de la única incluyen que quería, pero si el la vista incluida contiene cientos de líneas, aún estás mucho mejor. Por ejemplo:

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:custom="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" > 

    <!-- this is the beginning of your custom attribute include --> 
    <com.something.SingleSettingWrapper 
     android:id="@+id/my_wrapper" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     custom:labelText="@string/auto_lock_heading"> 
     <include layout="@layout/setting_single_item"/> 
    </com.something.SingleSettingWrapper> 
    <!-- this is the end of your custom attribute include --> 
</LinearLayout> 

En la práctica, esto parece funcionar bastante bien y es relativamente fácil de configurar. Espero que esto ayude a alguien.

+0

. Un poco demasiado complejo al envolver una vista en la vista –

Cuestiones relacionadas