Android | 获取ViewGroup的所有子元素

getChildAt(i) on只获取ViewGroup的直接子ViewGroup ,是否可以在不进行嵌套循环的情况下访问所有子节点?

( 来源 )

如果要获取所有子视图以及子ViewGroups的视图,则必须以递归方式执行此操作,因为API中没有提供开箱即用的设置。

 private ArrayList getAllChildren(View v) { if (!(v instanceof ViewGroup)) { ArrayList viewArrayList = new ArrayList(); viewArrayList.add(v); return viewArrayList; } ArrayList result = new ArrayList(); ViewGroup viewGroup = (ViewGroup) v; for (int i = 0; i < viewGroup.getChildCount(); i++) { View child = viewGroup.getChildAt(i); ArrayList viewArrayList = new ArrayList(); viewArrayList.add(v); viewArrayList.addAll(getAllChildren(child)); result.addAll(viewArrayList); } return result; } 

这将为您提供一个ArrayList,其中包含层次结构中的所有视图,然后您可以迭代它们。

本质上,如果代码在层次结构中find另一个ViewGroup,则此代码会调用自身,然后返回一个ArrayList以添加到更大的ArrayList中。

在撰写此答案时,接受的答案存在缺陷,因为它的结果中将包含重复内容。

对于那些在递归时遇到麻烦的人来说,这是一个非递归的替代方案。 你可以获得奖励积分,这也是对另一个答案的深度优先方法的广度优先搜索替代方案。

 private List getAllChildrenBFS(View v) { List visited = new ArrayList(); List unvisited = new ArrayList(); 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 

一些快速测试(没有正式的)表明这种替代方案也更快,尽管这很可能与另一个答案创建的新ArrayList实例的数量有关。 此外,结果可能会根据视图层次结构的垂直/水平方式而有所不同。

我以递归的方式重新实现了这个方法。 不确定它比MH更快,但至少它没有重复。

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

MH的答案包括给出方法的父视图,所以我创建了这个辅助方法(这是一个被调用的方法)。

我的意思是,如果在TextView(没有子节点)上调用此方法,则返回0而不是1。

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

TLDR:要计算所有孩子的复制和粘贴两种方法,请调用getAllChildren()

我不知道它是好还是不好。只是覆盖onViewAdded(View子)方法,只需在List添加List 。通过文档给它思考。当你编写自定义视图组时,这很有用

将新子项添加到此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(" "); } }