resource - recursos android studio
¿Cómo puedo asignar una ID a una vista mediante programación? (3)
En un archivo XML, podemos asignar una ID a una vista como android:id="@+id/something"
y luego llamar a findViewById()
, pero al crear una vista mediante programación, ¿cómo puedo asignar una ID?
Creo que setId()
no es lo mismo que la asignación predeterminada. setId()
es extra.
¿Alguien puede corregirme?
Visión general de Android id
Un id
Android es un número entero comúnmente utilizado para identificar vistas; esta id
se puede asignar a través de XML (cuando sea posible) y mediante código (mediante programación). La id
es más útil para obtener referencias para View
definidas en XML generadas por un Inflater
(como mediante el uso de setContentView
).
Asignar id
través de XML
- Agregue un atributo de
android:id="@+id/
somename"
a su vista. - Cuando se crea su aplicación, a
android:id
se le asignará unaint
única para usar en el código. -
R.id.
referencia a suandroid:id
int
value en el código usando "R.id.
somename" (efectivamente una constante). - esta
int
puede cambiar de una compilación a otra, así que nunca copies una id degen/
package.name/R.java
, solo usa "R.id.
somename". - (Además, una
id
asignada a unaPreference
en XML no se usa cuando laPreference
genera suView
).
Asignar id
por código (programáticamente)
- Configure manualmente los
id
consomeView.setId(
int);
- El
int
debe ser positivo, pero por lo demás arbitrario, puede ser lo que quieras (sigue leyendo si es espantoso). - Por ejemplo, si crea y numera varias vistas que representan elementos, puede usar su número de artículo.
Unicidad de id
s
-
XML
id
asignaciónXML
serán únicos. - Los
id
código asignado no tienen que ser únicos - Los
id
Asignados por código pueden (en teoría) entrar en conflicto con losid
con asignaciónXML
. - Estos
id
Conflictivos no importarán si se consultan correctamente (sigue leyendo) .
Cuándo (y por qué) las id
conflictivas no importan
-
findViewById(int)
repetirá en profundidad recursivamente a través de la jerarquía de vistas desde la vista que especifique y devolverá la primeraView
que encuentre con unid
correspondiente. - Siempre que no haya
id
asignados por código asignados antes de unaid
definida por XML en la jerarquía,findViewById(R.id.somename)
siempre devolverá la vista definida en XML asíid
''d.
Creación dinámica de vistas y asignación de ID
s
- En el diseño XML, defina un
ViewGroup
vacío conid
. - Tal como
LinearLayout
conandroid:id="@+id/placeholder"
. - Use el código para llenar el marcador de posición
ViewGroup
conView
s. - Si necesita o quiere, asigne cualquier
id
que sea conveniente para cada vista. Consulte estas vistas secundarias usando placeholder.findViewById (convenientInt);
API 17 introdujo
View.generateViewId()
que le permite generar una ID única.
Si elige mantener referencias a sus puntos de vista , asegúrese de crear una instancia con getApplicationContext()
y asegúrese de configurar cada referencia a null en onDestroy
. Aparentemente, filtrar la Activity
(colgarse de ella después de que se destruya) es un desperdicio ... :)
Reserve un android:id
XML android:id
para usar en el código
API 17 introdujo View.generateViewId()
que genera una ID única. (Gracias a take-chance-make-changes para señalar esto). *
Si su ViewGroup
no se puede definir a través de XML (o no lo desea), puede reservar el id. A través de XML para asegurarse de que siga siendo único:
Aquí, values / ids.xml define una id
personalizada:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="reservedNamedId" type="id"/>
</resources>
Luego, una vez que ViewGroup o View ha sido creado, puede adjuntar el ID personalizado
myViewGroup.setId(R.id.reservedNamedId);
Ejemplo de id
conflictiva
Para mayor claridad a modo de ejemplo ofuscante, examinemos lo que sucede cuando hay un conflicto de id
detrás de las escenas.
layout / mylayout.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 valor int
de 12
..
A continuación, MyActivity.java define algunas vistas de adiciones 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í que el placeholder
y uno de nuestros nuevos TextView
s tienen una id
de 12! Pero esto no es realmente un problema si consultamos las vistas secundarias del marcador 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
Puede usar View.setId(integer)
para esto. En el XML, aunque está configurando un Id. De cadena, esto se convierte en un número entero. Debido a esto, puede usar cualquier número entero (positivo) para las Views
que agrega programáticamente.
De acuerdo con la documentación de
View
El identificador no tiene que ser exclusivo en la jerarquía de esta vista. El identificador debe ser un número positivo.
Entonces puedes usar cualquier número entero positivo que te guste, pero en este caso puede haber algunas vistas con id equivalentes. Si desea buscar alguna vista en la jerarquía llamando a setTag con algunos objetos clave, puede ser útil.
Créditos a esta respuesta .
Sí, puede llamar a setId(value)
en cualquier vista con cualquier valor entero (positivo) que le guste y luego encontrarlo en el contenedor principal utilizando findViewById(value)
. Tenga en cuenta que es válido llamar a setId()
con el mismo valor para diferentes vistas de hermanos, pero findViewById()
devolverá solo el primero.