2011-12-06 20 views
132

Vista dada ¿Cómo puedo obtener las vistas secundarias dentro de ella?Android: ¿conseguir niños dentro de una vista?

Así que tengo una vista personalizada y el depurador muestra que debajo de mChildren hay otras 7 vistas. Necesito una forma de acceder a estas vistas, pero no parece que haya una API pública para hacer esto.

alguna sugerencia?

EDIT:

Mi vista personalizada hereda de AdapterView

Respuesta

248
for(int index=0; index<((ViewGroup)viewGroup).getChildCount(); ++index) { 
    View nextChild = ((ViewGroup)viewGroup).getChildAt(index); 
} 

hará eso?

+1

¿Cuál es el La mejor manera de hacer esto recursivamente y así generar una vista jerárquica objeto JSON? – jimbob

15

Siempre se puede acceder a través de puntos de vista del niño View.findViewById() http://developer.android.com/reference/android/view/View.html#findViewById(int).

Por ejemplo, dentro de una actividad/foto:

... 
private void init() { 
    View child1 = findViewById(R.id.child1); 
} 
... 

o si tiene una referencia a una vista:

... 
private void init(View root) { 
    View child2 = root.findViewById(R.id.child2); 
} 
+0

No tengo acceso a los identificadores, la IU se genera a través del código, estoy escribiendo automatización usando el robotium, entonces las cosas que puedo hacer son limitadas – aryaxt

5

Aquí es una sugerencia: se puede obtener el ID (especificada por ejemplo, mediante android:id="@+id/..My Str..) que se generó por R utilizando su nombre de pila (por ejemplo My Str). Un fragmento de código usando getIdentifier() método sería entonces:

public int getIdAssignedByR(Context pContext, String pIdString) 
{ 
    // Get the Context's Resources and Package Name 
    Resources resources = pContext.getResources(); 
    String packageName = pContext.getPackageName(); 

    // Determine the result and return it 
    int result = resources.getIdentifier(pIdString, "id", packageName); 
    return result; 
} 

Desde dentro de una Activity, un ejemplo de uso junto con findViewById sería:

// Get the View (e.g. a TextView) which has the Layout ID of "UserInput" 
int rID = getIdAssignedByR(this, "UserInput") 
TextView userTextView = (TextView) findViewById(rID); 
45

Si usted no sólo quiere conseguir todos los niños directos pero todos de los niños los niños y así sucesivamente, lo que tiene que hacer de forma recursiva:

private ArrayList<View> getAllChildren(View v) { 

    if (!(v instanceof ViewGroup)) { 
     ArrayList<View> viewArrayList = new ArrayList<View>(); 
     viewArrayList.add(v); 
     return viewArrayList; 
    } 

    ArrayList<View> result = new ArrayList<View>(); 

    ViewGroup vg = (ViewGroup) v; 
    for (int i = 0; i < vg.getChildCount(); i++) { 

     View child = vg.getChildAt(i); 

     ArrayList<View> viewArrayList = new ArrayList<View>(); 
     viewArrayList.add(v); 
     viewArrayList.addAll(getAllChildren(child)); 

     result.addAll(viewArrayList); 
    } 
    return result; 
} 

para utilizar el resultado se podría hacer algo como esto:

// check if a child is set to a specific String 
    View myTopView; 
    String toSearchFor = "Search me"; 
    boolean found = false; 
    ArrayList<View> allViewsWithinMyTopView = getAllChildren(myTopView); 
    for (View child : allViewsWithinMyTopView) { 
     if (child instanceof TextView) { 
      TextView childTextView = (TextView) child; 
      if (TextUtils.equals(childTextView.getText().toString(), toSearchFor)) { 
       found = true; 
      } 
     } 
    } 
    if (!found) { 
     fail("Text '" + toSearchFor + "' not found within TopView"); 
    } 
+6

Esta llamada no se guarda, como p. child puede ser de tipo View y no de ViewGroup, por lo que la llamada recursiva de getAllChildren podría causar una excepción, ya que el lanzamiento falla. Por lo tanto, debe agregar un if (! (V instanciade ViewGroup)) return; antes del molde –

+2

Sugerencia pequeña: reemplace el ciclo for con 'for (int i = 0, n = vg.getChildCount(); i ArtOfWarfare

+0

Cambié el código debido a la sugerencia de Phil Diegmann. Espero que esto ayude. Funciona para mi. – IHeartAndroid

13

sólo voy a dar esta respuesta como una alternativa @ algoritmo recursivo de IHeartAndroid para descubrir todo niño View s en una jerarquía de vistas. Tenga en cuenta que en el momento de escribir esto, , la solución recursiva está defectuosa, ya que contendrá duplicados en su resultado.

Para aquellos que tienen problemas para resolver recursiones, aquí hay una alternativa no recursiva. Obtiene puntos de bonificación por darse cuenta de que esta también es una alternativa de búsqueda que amplía la anchura al primer profundidad-primero enfoque de la solución recursiva.

private List<View> getAllChildrenBFS(View v) { 
    List<View> visited = new ArrayList<View>(); 
    List<View> unvisited = new ArrayList<View>(); 
    unvisited.add(v); 

    while (!unvisited.isEmpty()) { 
     View child = unvisited.remove(0); 
     visited.add(child); 
     if (!(child instanceof ViewGroup)) continue; 
     ViewGroup group = (ViewGroup) child; 
     final int childCount = group.getChildCount(); 
     for (int i=0; i<childCount; i++) unvisited.add(group.getChildAt(i)); 
    } 

    return visited; 
} 

Un par de pruebas rápidas (nada formal) sugieren que esta alternativa es también más rápido, a pesar de que tiene más probable es que ver con el número de nuevos casos ArrayList crea la otra respuesta. Además, los resultados pueden variar en función de cuán vertical/horizontal sea la jerarquía de vistas.

Cruz-registrado desde: Android | Get all children elements of a ViewGroup

0

Con el fin de refrescar un diseño de tabla (TableLayout) que terminé tener que utilizar el enfoque recursivo mencionado anteriormente para que los niños de todos los niños y así sucesivamente.

Mi situación se simplificó un poco porque solo necesitaba trabajar con LinearLayout y esas clases se extendían desde allí, como TableLayout. Y solo estaba interesado en encontrar niños de TextView. Pero creo que todavía es aplicable a esta pregunta.

La clase final se ejecuta como un subproceso independiente, lo que significa que puede hacer otras cosas en segundo plano antes de analizar para los secundarios. El código es pequeño y simple y se puede encontrar en github: https://github.com/jkincali/Android-LinearLayout-Parser

Cuestiones relacionadas