¿Cómo puedo asignar una ID a una vista mediante programación?
En un archivo XML, podemos asignar una ID a una vista como android:id="@+id/something"
y luego llamarla findViewById()
, pero al crear una vista mediante programación, ¿cómo asigno una ID?
Creo setId()
que no es lo mismo que la asignación predeterminada. setId()
es adicional.
¿Alguien puede corregirme?
id
Descripción general de Android
Un Android id
es un número entero comúnmente utilizado para identificar vistas; esto id
se puede asignar mediante XML (cuando sea posible) y mediante código (mediante programación). Es id
más útil para obtener referencias de View
mensajes de correo definidos en XML generados por un Inflater
(como mediante el uso de setContentView
.)
Asignar id
víaXML
- Agregue un atributo de
android:id="@+id/
algún nombre"
a su vista. - Cuando se cree su aplicación, se le
android:id
asignará un código únicoint
para su uso en el código. - Haga referencia a su
android:id
valorint
en el código usando "R.id.
algún nombre" (efectivamente, una constante). - esto
int
puede cambiar de una compilación a otra , así que nunca copie una identificación degen/
package.name/R.java
, solo use "R.id.
somename". - (Además, un
id
asignado a unPreference
XML no se utiliza cuandoPreference
genera suView
).
Asignar id
mediante código (programáticamente)
- Establecer s manualmente
id
usandosomeView.setId(
int);
- Debe
int
ser positivo, pero por lo demás es arbitrario: puede ser lo que quieras (sigue leyendo si esto te da miedo). - Por ejemplo, si crea y numera varias vistas que representan artículos, puede usar su número de artículo.
Unicidad de id
s
XML
-los s asignadosid
serán únicos.- Los mensajes de correo electrónico asignados
id
no tienen que ser únicos - Los s asignados por código
id
pueden (teóricamente) entrar en conflicto con los sXML
asignadosid
. - Estos
id
mensajes de correo electrónico en conflicto no importarán si se consultan correctamente (siga leyendo) .
Cuándo (y por qué) los mensajes conflictivos id
no importan
findViewById(int)
iterará primero en profundidad de forma recursiva a través de la jerarquía de vistas desde la Vista que especifique y devolverá la primeraView
que encuentre con una coincidenciaid
.- Siempre que no haya códigos asignados
id
antes de un XML definidoid
en la jerarquía,findViewById(R.id.somename)
siempre devolverá la Vista definida por XML asíid
.
Crear vistas y asignar ID
dinámicamente
- En el diseño XML, defina un vacío
ViewGroup
conid
. - Como por ejemplo
LinearLayout
conandroid:id="@+id/placeholder"
. - Utilice código para completar el marcador de posición
ViewGroup
conView
s. - Si lo necesita o lo desea, asigne los correos electrónicos
id
que sean convenientes para cada vista. Consulta estas vistas secundarias usando placeholder.findViewById(convenientInt);
Se introdujo API 17
View.generateViewId()
que le permite generar una identificación única.
Si elige mantener las referencias a sus vistas , asegúrese de crear instancias de ellas getApplicationContext()
y asegúrese de establecer cada referencia como nula en onDestroy
. Aparentemente , filtrar el Activity
(colgarlo después de destruirlo) es un desperdicio... :)
Reserve un XML android:id
para usarlo en el código
Se introdujo API 17 View.generateViewId()
que genera una identificación única. (Gracias a take-chances-make-changes por señalar esto).*
Si ViewGroup
no se puede definir a través de XML (o no desea que lo sea), puede reservar la identificación a través de XML para asegurarse de que siga siendo única:
Aquí, value/ids.xml define una costumbre id
:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="reservedNamedId" type="id"/>
</resources>
Luego, una vez que se haya creado el ViewGroup o View, puede adjuntar la identificación personalizada
myViewGroup.setId(R.id.reservedNamedId);
id
Ejemplo contradictorio
Para mayor claridad a modo de ejemplo confuso, examinemos lo que sucede cuando hay un id
conflicto detrás de escena.
diseño/midiseño.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/placeholder"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
Para simular un conflicto, digamos que nuestra última compilación asignó R.id.placeholder
( @+id/placeholder
) un int
valor de 12
..
A continuación, MyActivity.java define algunas vistas agregadas mediante programación (mediante código):
int placeholderId = R.id.placeholder; // placeholderId==12
// returns *placeholder* which has id==12:
ViewGroup placeholder = (ViewGroup)this.findViewById(placeholderId);
for (int i=0; i<20; i++){
TextView tv = new TextView(this.getApplicationContext());
// One new TextView will also be assigned an id==12:
tv.setId(i);
placeholder.addView(tv);
}
¡Así placeholder
que uno de nuestros nuevos TextView
tiene un puntaje id
de 12! Pero esto no es realmente un problema si consultamos las vistas secundarias de los marcadores de posición:
// Will return a generated TextView:
placeholder.findViewById(12);
// Whereas this will return the ViewGroup *placeholder*;
// as long as its R.id remains 12:
Activity.this.findViewById(12);
*No es tan malo
Puedes usar el View.setId(integer)
para esto. En XML, aunque esté configurando una identificación de cadena, esta se convierte en un número entero. Debido a esto, puede usar cualquier número entero (positivo) para agregar Views
mediante programación.
Según
View
la documentaciónNo es necesario que el identificador sea único en la jerarquía de esta vista. El identificador debe ser un número positivo.
Por lo tanto, puede utilizar cualquier número entero positivo que desee, pero en este caso puede haber algunas vistas con identificaciones equivalentes. Si desea buscar alguna vista en la jerarquía, puede ser útil llamar a setTag con algunos objetos clave.
Créditos a esta respuesta .
Sí, puede llamar setId(value)
a cualquier vista con cualquier valor entero (positivo) que desee y luego encontrarlo en el contenedor principal usando findViewById(value)
. Tenga en cuenta que es válido llamar setId()
con el mismo valor para diferentes vistas hermanas, pero findViewById()
solo devolverá la primera.