xml - layout_width - linearlayout android studio
Declarar un elemento personalizado de la interfaz de usuario de Android usando XML (6)
Además de la respuesta más votada.
obtenerStyledAttributes ()
Quiero agregar algunas palabras sobre el uso de obtención de estilo de atributos () cuando creamos una vista personalizada con los atributos predefinidos de Android: xxx. Especialmente cuando usamos TextAppearance.
Como se mencionó en "2. Crear constructores", la vista personalizada obtiene AttributeSet en su creación. Uso principal que podemos ver en el código fuente de TextView (API 16).
final Resources.Theme theme = context.getTheme();
// TextAppearance is inspected first, but let observe it later
TypedArray a = theme.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.TextView, defStyle, 0);
int n = a.getIndexCount();
for (int i = 0; i < n; i++)
{
int attr = a.getIndex(i);
// huge switch with pattern value=a.getXXX(attr) <=> a.getXXX(a.getIndex(i))
}
a.recycle();
¿Qué podemos ver aquí?
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
El conjunto de atributos se procesa por tema de acuerdo con la documentación. Los valores de los atributos se compilan paso a paso. Los primeros atributos se rellenan desde el tema, luego los valores se reemplazan por los valores de estilo y, finalmente, los valores exactos de XML para una instancia de vista especial reemplazan a otros.
Array de atributos solicitados - com.android.internal.R.styleable.TextView
Es un conjunto ordinario de constantes. Si estamos solicitando atributos estándar, podemos construir esta matriz manualmente.
Lo que no se menciona en la documentación: orden del resultado de los elementos de TypedArray.
Cuando la vista personalizada se declara en attrs.xml, se generan constantes especiales para los índices de atributos. Y podemos extraer valores de esta manera: a.getString(R.styleable.MyCustomView_android_text)
. Pero para int[]
manual int[]
no hay constantes. Supongo que getXXXValue (arrayIndex) funcionará bien.
Y otra pregunta es: "¿Cómo podemos reemplazar las constantes internas y solicitar atributos estándar?" Podemos usar los valores de android.R.attr. *.
Entonces, si queremos usar el atributo de apariencia de texto estándar en la vista personalizada y leer sus valores en el constructor, podemos modificar el código de TextView de esta manera:
ColorStateList textColorApp = null;
int textSize = 15;
int typefaceIndex = -1;
int styleIndex = -1;
Resources.Theme theme = context.getTheme();
TypedArray a = theme.obtainStyledAttributes(attrs, R.styleable.CustomLabel, defStyle, 0);
TypedArray appearance = null;
int apResourceId = a.getResourceId(R.styleable.CustomLabel_android_textAppearance, -1);
a.recycle();
if (apResourceId != -1)
{
appearance =
theme.obtainStyledAttributes(apResourceId, new int[] { android.R.attr.textColor, android.R.attr.textSize,
android.R.attr.typeface, android.R.attr.textStyle });
}
if (appearance != null)
{
textColorApp = appearance.getColorStateList(0);
textSize = appearance.getDimensionPixelSize(1, textSize);
typefaceIndex = appearance.getInt(2, -1);
styleIndex = appearance.getInt(3, -1);
appearance.recycle();
}
Donde se define CustomLabel:
<declare-styleable name="CustomLabel">
<!-- Label text. -->
<attr name="android:text" />
<!-- Label text color. -->
<attr name="android:textColor" />
<!-- Combined text appearance properties. -->
<attr name="android:textAppearance" />
</declare-styleable>
Tal vez, estoy equivocado de alguna manera, pero la documentación de Android en obtención de estiloAtributos () es muy pobre.
Ampliación de componente de interfaz de usuario estándar
Al mismo tiempo, solo podemos extender el componente UI estándar, utilizando todos sus atributos declarados. Este enfoque no es tan bueno, porque TextView, por ejemplo, declara muchas propiedades. Y será imposible implementar la funcionalidad completa en anular onMeasure () y onDraw ().
Pero podemos sacrificar amplia reutilización teórica del componente personalizado. Diga "Sé exactamente qué funciones usaré" y no comparta el código con nadie.
Luego podemos implementar el constructor CustomComponent(Context, AttributeSet, defStyle)
. Después de llamar a super(...)
tendremos todos los atributos analizados y disponibles a través de los métodos de obtención.
¿Cómo declaro un elemento de la interfaz de usuario de Android utilizando XML?
Gran referencia. ¡Gracias! Una adición a ella:
Si tiene un proyecto de biblioteca incluido que ha declarado atributos personalizados para una vista personalizada, debe declarar el espacio de nombres de su proyecto, no el de la biblioteca. P.ej:
Dado que la biblioteca tiene el paquete "com.example.library.customview" y el proyecto de trabajo tiene el paquete "com.example.customview", entonces:
No funcionará (muestra el error "error: no se encontró un identificador de recurso para el atributo ''newAttr'' en el paquete ''com.example.library.customview''"):
<com.library.CustomView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.library.customview"
android:id="@+id/myView"
app:newAttr="value" />
Trabajará:
<com.library.CustomView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.example.customview"
android:id="@+id/myView"
app:newAttr="value" />
La Guía del desarrollador de Android tiene una sección llamada Creación de componentes personalizados . Desafortunadamente, la discusión de los atributos XML solo cubre declarar el control dentro del archivo de diseño y no manejar realmente los valores dentro de la inicialización de clase. Los pasos son los siguientes:
1. Declarar atributos en los values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyCustomView">
<attr name="android:text"/>
<attr name="android:textColor"/>
<attr name="extraInformation" format="string" />
</declare-styleable>
</resources>
Observe el uso de un nombre no calificado en la etiqueta declare-styleable
. Los atributos de Android no estándar, como información extraInformation
deben tener su tipo declarado. Las etiquetas declaradas en la superclase estarán disponibles en subclases sin tener que volver a declararlas.
2. Crear constructores.
Dado que hay dos constructores que utilizan un AttributeSet
para la inicialización, es conveniente crear un método de inicialización separado para que los constructores llamen.
private void init(AttributeSet attrs) {
TypedArray a=getContext().obtainStyledAttributes(
attrs,
R.styleable.MyCustomView);
//Use a
Log.i("test",a.getString(
R.styleable.MyCustomView_android_text));
Log.i("test",""+a.getColor(
R.styleable.MyCustomView_android_textColor, Color.BLACK));
Log.i("test",a.getString(
R.styleable.MyCustomView_extraInformation));
//Don''t forget this
a.recycle();
}
R.styleable.MyCustomView
es un recurso int[]
autogenerado donde cada elemento es el ID de un atributo. Los atributos se generan para cada propiedad en el XML agregando el nombre del atributo al nombre del elemento. Por ejemplo, R.styleable.MyCustomView_android_text
contiene el atributo MyCustomView
para MyCustomView
. Los atributos se pueden recuperar de TypedArray
usando varias funciones de get
. Si el atributo no está definido en el definido en el XML, entonces se devuelve null
. Excepto, por supuesto, si el tipo de retorno es primitivo, en cuyo caso se devuelve el segundo argumento.
Si no desea recuperar todos los atributos, es posible crear esta matriz manualmente. La ID para los atributos estándar de Android se incluye en android.R.attr
, mientras que los atributos para este proyecto están en R.attr
.
int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};
Tenga en cuenta que no debe usar nada en android.R.styleable
, ya que este hilo puede cambiar en el futuro. Todavía está en la documentación, ya que ver todas estas constantes en un solo lugar es útil.
3. Utilícelo en archivos de layout/main.xml
como layout/main.xml
Incluya la declaración de espacio de nombres xmlns:app="http://schemas.android.com/apk/res-auto"
en el elemento xml de nivel superior. Los espacios de nombres proporcionan un método para evitar los conflictos que a veces ocurren cuando diferentes esquemas usan los mismos nombres de elementos (consulte este artículo para obtener más información). La URL es simplemente una manera de identificar esquemas de forma única: en realidad, no es necesario alojar esa URL . Si esto no parece estar haciendo nada, es porque en realidad no es necesario agregar el prefijo de espacio de nombres a menos que necesite resolver un conflicto.
<com.mycompany.projectname.MyCustomView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:text="Test text"
android:textColor="#FFFFFF"
app:extraInformation="My extra information"
/>
Haga referencia a la vista personalizada utilizando el nombre completo.
Ejemplo de LabelView para Android
Si desea un ejemplo completo, mire la muestra de vista de etiqueta de Android.
TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
CharSequences=a.getString(R.styleable.LabelView_text);
<declare-styleable name="LabelView">
<attr name="text"format="string"/>
<attr name="textColor"format="color"/>
<attr name="textSize"format="dimension"/>
</declare-styleable>
<com.example.android.apis.view.LabelView
android:background="@drawable/blue"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
app:text="Blue" app:textSize="20dp"/>
Esto está contenido en un LinearLayout
con un atributo de espacio de nombres: xmlns:app="http://schemas.android.com/apk/res-auto"
Campo de golf
Muchas gracias por la primera respuesta.
En cuanto a mí, solo tuve un problema con eso. Al inflar mi vista, tuve un error: java.lang.NoSuchMethodException: MyView (Contexto, Atributos)
Lo resolví creando un nuevo constructor:
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// some code
}
Espero que esto ayude!
Parece que Google ha actualizado su página de desarrollador y ha agregado varios entrenamientos allí.
Uno de ellos se ocupa de la creación de vistas personalizadas y se puede encontrar here
Puede incluir cualquier archivo de diseño en otro archivo de diseño como
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="30dp" >
<include
android:id="@+id/frnd_img_file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
layout="@layout/include_imagefile"/>
<include
android:id="@+id/frnd_video_file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
layout="@layout/include_video_lay" />
<ImageView
android:id="@+id/downloadbtn"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_centerInParent="true"
android:src="@drawable/plus"/>
</RelativeLayout>
aquí los archivos de diseño en la etiqueta de inclusión son otros archivos de diseño .xml en la misma carpeta de res.