原文http://android-wtf.com/2013/06/how-to-easily-traverse-any-view-hierarchy-in-android/
翻墙看的一篇文章,直接复制过来了,懒得翻译了
Have you ever wanted to find all the views marked with a specific tag? Well, the Android SDK only allows to find the first one. How about finding a specific type of views?
Faced with this very problem, I had to write a couple of utility classes, and now I’m sharing it. Before the library code I’ll show a demonstration of its usage. Here’s how you can traverse the whole view hierarchy of your Activity
:
ViewGroup root = (ViewGroup) findViewById(android.R.id.content); LayoutTraverser.build(new LayoutTraverser.Processor() { @Override public void process(View view) { // do stuff with the view } }).traverse(root);
You can pass any ViewGroup
instance (such LinearLayout
, RelativeLayout
and FrameLayout
) to the traverse
method, and for every view under the hierarchy (including the root ViewGroup
itself) the process
method will be executed.
If you want to traverse multiple hierarchies using the same processing logic:
LayoutTraverser traverser = LayoutTraverser.build(new LayoutTraverser.Processor() { @Override public void process(View view) { // do stuff with the view } }); traverser.traverse(root); traverser.traverse(root2); traverser.traverse(root3);
There are two static methods included which I believe cover the majority of use-cases: finding views by tag and finding views of a specific type:
// all views tagged "coolView" under "root" List<View> coolViews = Views.find(root, "coolView"); // all ImageView views under "root" List<ImageView> imageViews = Views.find(root, ImageView.class);
The LayoutTraverser
class:
package com.androidwtf.android; import android.view.View; import android.view.ViewGroup; public class LayoutTraverser { public interface Processor { void process(View view); } private final Processor processor; private LayoutTraverser(Processor processor) { this.processor = processor; } public static LayoutTraverser build(Processor processor) { return new LayoutTraverser(processor); } public void traverse(ViewGroup root) { final int childCount = root.getChildCount(); for (int i = 0; i < childCount; ++i) { final View child = root.getChildAt(i); processor.process(child); if (child instanceof ViewGroup) { traverse((ViewGroup) child); } } } }
The Views
class:
package com.androidwtf.android; import android.view.View; import android.view.ViewGroup; import java.util.ArrayList; import java.util.List; final public class Views { private Views() {} public static List<View> find(ViewGroup root, Object tag) { FinderByTag finderByTag = new FinderByTag(tag); LayoutTraverser.build(finderByTag).traverse(root); return finderByTag.getViews(); } public static <T extends View> List<T> find(ViewGroup root, Class<T> type) { FinderByType<T> finderByType = new FinderByType<T>(type); LayoutTraverser.build(finderByType).traverse(root); return finderByType.getViews(); } private static class FinderByTag implements LayoutTraverser.Processor { private final Object searchTag; private final List<View> views = new ArrayList<View>(); private FinderByTag(Object searchTag) { this.searchTag = searchTag; } @Override public void process(View view) { Object viewTag = view.getTag(); if (viewTag != null && viewTag.equals(searchTag)) { views.add(view); } } private List<View> getViews() { return views; } } private static class FinderByType<T extends View> implements LayoutTraverser.Processor { private final Class<T> type; private final List<T> views; private FinderByType(Class<T> type) { this.type = type; views = new ArrayList<T>(); } @Override @SuppressWarnings("unchecked") public void process(View view) { if (type.isInstance(view)) { views.add((T) view); } } public List<T> getViews() { return views; } } }
Help fellow developers by tweeting or sharing this post!