At the time of writing this answer, the accepted answer is flawed in that it will contains duplicates in its result.
For those who have trouble wrapping their head around recursion, here's a non-recursive alternative. You get bonus points for realizing this is also a breadth-first search alternative to the depth-first approach of the other answer.
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;
}
A couple of quick tests (nothing formal) suggest this alternative is also faster, although that has most likely to do with the number of new ArrayList
instances the other answer creates. Also, results may vary based on how vertical/horizontal the view hierarchy is.
(source)
If you want to get all the child views, as well as the views within children ViewGroups
, you must do it recursively, since there is no provision in the API to do this out of the box.
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;
}
This will give you an ArrayList with all the Views in the hierarchy which you can then iterate over.
Essentially, this code call itself if it finds another ViewGroup in the hierarchy, and then returns an ArrayList to be added to the bigger ArrayList.
ViewGroup
using forEach{}
If you want to iterate through all childViews, you can use predefined kotlin extension forEach
in any ViewGroup. Example:
yourViewGroup.forEach{ childView ->
// do something with this childView
}
.children.toList
in a ViewGroup
To return a list of Views
, you can use function children
to return a Sequence
and then use toList()
to transform it to a List
. Example:
val yourChildViewsList: List<View> = yourViewGroup.children.toList()
I've reimplemented this method in a recursive way. Not sure it's faster than MH's, but at least it has no duplicates.
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's answer includes the parent view which is being given to the method, so I created this auxiliary method (which is the one to be called).
I mean, if you call this method on a TextView (which has no children), it returns 0 instead of 1.
private List<View> getAllChildren(View v) {
List list = getAllViews(v);
list.remove(v);
return list;
}
TLDR: to count all children copy and paste both methods, call getAllChildren()
I don't know if its good or not.just override the onViewAdded(View child) method and just add the views in List<View>
.Give it thoughts.by the docs.This usefull when you are writing custom view group
Called when a new child is added to this ViewGroup. Overrides should always call super.onViewAdded.
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
views.add(child);//add in list and then use it later
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With