android - tipos - para qué sirve el elemento data-* en html
Incluir diseño con atributos personalizados. (7)
Desafortunadamente, lo único que puedo aportar es que tampoco pude 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.
Realizo un diseño complejo y uso "incluir" para mi componente personalizado, como este
<include layout="@layout/topbar"/>
Y topbar se define así:
<?xml version="1.0" encoding="utf-8"?>
<my.package.TopBarLayout
... a lot of code
Ahora, quiero pasar mis atributos personalizados definidos a "barra superior" como esto
<include layout="@layout/topbar" txt:trName="@string/contacts"/>
Pero no tengo resultado. Entendí desde esa página que no puedo establecer atributos, sino id, altura y anchura.
Entonces, ¿cómo puedo pasar mis atributos personalizados definidos para incluir, y cómo puedo hacer que funcione?
Me encontré con este problema hoy. Para lo que valga, creo que hay una solución directa. En lugar de agregar atributos a la etiqueta de inclusión, cree una vista de envoltorio personalizado para los atributos de inclusión y adición a eso. Luego, haga la inclusión desde el envoltorio. Haga que la implementación de la clase contenedora extraiga los atributos y pase a su hijo único, que es la vista raíz del diseño de inclusión.
Entonces, digamos que declaramos algunos atributos personalizados para un contenedor llamado SingleSettingWrapper como este:
<declare-styleable name="SingleSettingWrapper">
<attr name="labelText" format="string"/>
</declare-styleable>
Luego, creamos dos clases de vista personalizadas: una para el contenedor (SingleSettingWrapper) y otra para el hijo (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 diseño complejo allí que queramos. Solo pondré algo básico, pero realmente puedes incluir lo que sea.
<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 el contenedor (esta es la clave), leemos todos nuestros atributos personalizados en el constructor. Luego, anulamos onViewAdded () 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, también puede implementar el niño y hacer que reciba mensajes del envoltorio y modificarse (en lugar de hacer que el envoltorio modifique al 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 en los que quiso <include>
su diseño contendrá aproximadamente 7 líneas de XML para el contenedor + incluir en lugar del único que desea, pero si la vista incluida contiene cientos de Todavía 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 sencillo de configurar. Espero que esto ayude a alguien.
No es posible crear atributos distintos a los parámetros de diseño, visibilidad o ID en una etiqueta de inclusión. Esto incluye atributos personalizados.
Puede verificar esto mirando 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 solo aplica el ID y los atributos de visibilidad al diseño incluido.
No es posible usarlo con atributos personalizados, o cualquier otro atributo que no sea el indicado en la página de la API (hasta al menos 5.0.0):
Sé que esta es una pregunta antigua, pero la encontré y descubrí que ahora es posible gracias a Data Binding.
Primero necesitas habilitar el enlace de datos en tu proyecto.
Luego, agregue el enlace de datos al diseño 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>
Finalmente, pase la variable del diseño principal al diseño incluido de esta manera:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
...
</data>
...
xmlns:app="http://schemas.android.com/apk/res-auto"
...
<include layout="@layout/included_layout"
android:id="@+id/title"
app:title="@{@string/title}"/>
...
</layout>
Tenía la misma pregunta. Después de visitar este hilo, terminé usando los métodos setTag()
para adjuntar información de identificación a cada View
durante los onCreate()
, y luego getTag()
para recuperarla más adelante.
Tienes que incluir en tu elemento xml raíz tu espacio de nombres personalizado. Si el nombre de su paquete es com.example.test, su XML debe ser 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/