Android | Получить все дочерние элементы группы ViewGroup

getChildAt(i) on получает только прямые дочерние ViewGroup , возможно ли получить доступ ко всем ViewGroup без выполнения вложенных циклов?

Solutions Collecting From Web of "Android | Получить все дочерние элементы группы ViewGroup"

( Источник )

Если вы хотите получить все дочерние представления, а также представления в дочерних ViewGroups , вы должны сделать это рекурсивно, поскольку в API нет никакого положения, чтобы сделать это из коробки.

 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 viewGroup = (ViewGroup) v; for (int i = 0; i < viewGroup.getChildCount(); i++) { View child = viewGroup.getChildAt(i); ArrayList<View> viewArrayList = new ArrayList<View>(); viewArrayList.add(v); viewArrayList.addAll(getAllChildren(child)); result.addAll(viewArrayList); } return result; } 

Это даст вам ArrayList со всеми представлениями в иерархии, которые вы затем можете перебрать.

По сути, этот код вызывает себя, если он находит другую ViewGroup в иерархии, а затем возвращает ArrayList для добавления в более крупный ArrayList.

Во время написания этого ответа принятый ответ ошибочен тем, что он будет содержать дубликаты в своем результате.

Для тех, у кого есть проблемы, обертывание головы вокруг рекурсии, вот нерекурсивная альтернатива. Вы получаете бонусные баллы за то, что понимаете, что это также альтернативный вариант поиска по глубине первого ответа.

 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; } 

Несколько быстрых тестов (без формальных) показывают, что эта альтернатива также быстрее, хотя это, скорее всего, связано с количеством новых экземпляров ArrayList создает другой ответ. Кроме того, результаты могут варьироваться в зависимости от вертикальной / горизонтальной иерархии представлений.

Я повторил этот метод рекурсивным образом. Не уверен, что это быстрее, чем MH, но по крайней мере у него нет дубликатов.

 private List<View> getAllViews(View v) { if (!(v instanceof ViewGroup) || ((ViewGroup) v).getChildCount() == 0) // It's a leaf { List<View> r = new ArrayList<View>(); r.add(v); return r; } else { List<View> list = new ArrayList<View>(); list.add(v); // If it's an internal node add itself int children = ((ViewGroup) v).getChildCount(); for (int i=0;i<children;++i) { list.addAll(getAllViews(((ViewGroup) v).getChildAt(i))); } return list; } } 

Ответ MH включает родительское представление, которое передается методу, поэтому я создал этот вспомогательный метод (который должен быть вызван).

Я имею в виду, если вы вызываете этот метод в TextView (у которого нет детей), он возвращает 0 вместо 1.

 private List<View> getAllChildren(View v) { List list = getAllViews(v); list.remove(v); return list; } 

TLDR: чтобы подсчитать всех детей, скопируйте и вставьте оба метода, вызовите getAllChildren ()

Я не знаю, хорошо ли это или нет. Просто переопределите метод onViewAdded (View child) и просто добавьте представления в List<View> .Give it thoughts.by в документах. Это полезно, когда вы пишете пользовательскую группу просмотра

Вызывается, когда новый ребенок добавляется в эту группу ViewGroup. Переопределения должны всегда вызывать super.onViewAdded.

 @Override public void onViewAdded(View child) { super.onViewAdded(child); views.add(child);//add in list and then use it later } 

Вот мое (рекурсивное) решение, которое печатает иерархию следующим образом:

 android.widget.LinearLayout children:2 id:-1 android.view.View id:2131624246 android.widget.RelativeLayout children:2 id:2131624247 android.support.v7.widget.AppCompatTextView id:2131624248 android.support.v7.widget.SwitchCompat id:2131624249 public static String getViewHierarcy(ViewGroup v) { StringBuffer buf = new StringBuffer(); printViews(v, buf, 0); return buf.toString(); } private static String printViews(ViewGroup v, StringBuffer buf, int level) { final int childCount = v.getChildCount(); v.getId(); indent(buf, level); buf.append(v.getClass().getName()); buf.append(" children:"); buf.append(childCount); buf.append(" id:"+v.getId()); buf.append("\n"); for (int i = 0; i < childCount; i++) { View child = v.getChildAt(i); if ((child instanceof ViewGroup)) { printViews((ViewGroup) child, buf, level+1); } else { indent(buf, level+1); buf.append(child.getClass().getName()); buf.append(" id:"+child.getId()); buf.append("\n"); } } return buf.toString(); } private static void indent(StringBuffer buf, int level) { for (int i = 0; i < level; i++) { buf.append(" "); } }