枚举/迭代活动中的所有视图?

时间:2011-02-02 08:33:18

标签: android iterator

有没有办法遍历Activity中的所有视图?类似的东西:

Iterator it = getViewIterator();
...

这根本存在吗?

8 个答案:

答案 0 :(得分:17)

如果您的所有观看次数都在LinearLayoutcontainer扩展ViewGroup,那么您可以使用getChildCount()getChildAt(int)这两个函数进行迭代所有的 载有意见。

希望这有帮助。

答案 1 :(得分:8)

假设“您的活动中的所有视图”是指层次结构中的每个视图,Android中没有此类Iterator或任何内容可以让您迭代所有视图。

ViewGroupgetChildCountgetChildAt种方法,但它们与ViewGroup的直接子女有关。因此,您需要访问每个孩子,并检查它本身是否为ViewGroup,依此类推。长话短说,我想要这样的功能来查找匹配特定标签的所有视图(findViewWithTag只返回第一个)。这是一个可以迭代所有视图的类:

public class LayoutTraverser {

    private final Processor processor;


    public interface Processor {
        void process(View view);
    }

    private LayoutTraverser(Processor processor) {
        this.processor = processor;
    }

    public static LayoutTraverser build(Processor processor) {
        return new LayoutTraverser(processor);
    }

    public View traverse(ViewGroup root) {
        final int childCount = root.getChildCount();

        for (int i = 0; i < childCount; ++i) {
            final View child = root.getChildAt(i);

            if (child instanceof ViewGroup) {
                traverse((ViewGroup) child);
            }
        }
        return null;
    }
}

像这样使用:

LayoutTraverser.build(new LayoutTraverser.Processor() {
  @Override
  public void process(View view) {
    // do stuff with the view
  }
}).traverse(viewGroup);

答案 2 :(得分:1)

活动通常包含一个主布局容器,其中放置了所有其他视图。 使用主布局容器的引用。遍历其子节点(使用getChild(postion),getchildcount()等)。如果任何一个孩子本身就是一个容器,那么在它上面应用相同的功能。这有点像遍历一个树结构

答案 3 :(得分:1)

以下是我的示例,基于Harry Joy's answer。它遍历父ViewGroup的所有层次结构,以查看其中任何位置的任何视图是否为Button

private boolean doesViewGroupContainButton(ViewGroup parentView) {

        int numChildViews = parentView.getChildCount();
        for (int i = 0; i < numChildViews; i++) {
            View childView = parentView.getChildAt(i);
            if (childView instanceof ViewGroup) {
                if (doesViewContainButton((ViewGroup)childView)) {
                    return true;
                }
            }
            else if (childView instanceof Button) {
                return true;
            }
        }
        return false;

    }

答案 4 :(得分:0)

如果你真的需要一个迭代器,api中没有类似的东西。你必须自己编写一个基于Harry Joy和Javanator建议的逻辑。

答案 5 :(得分:0)

如果你想避免丑陋的(int i = 0; ....) 你可以使用静态包装器

public class Tools
{
    public static Iterable<View> getChildViews(final ViewGroup view)
    {
        return new Iterable<View>()
        {
            int i = -1;

            @NonNull
            @Override
            public Iterator<View> iterator()
            {
                return new Iterator<View>()
                {
                    int i = -1;
                    @Override
                    public boolean hasNext()
                    {
                        return i < view.getChildCount();
                    }

                    @Override
                    public View next()
                    {
                        return view.getChildAt(++i);
                    }
                };
            }

        };
    }
}

并像这样使用

for (View view :  Tools.getChildViews(viewGroup))

当然,由于每次迭代时都要创建一个新的Iteratable对象,因此效率稍差,但如果你愿意的话,你可以在此基础上建立一个更有效的算法。

答案 6 :(得分:0)

Rx Java解决方案

    public static Observable<View> iterate(@NonNull View root) {
        return Observable.create(emitter -> {
            iterate(root, emitter);
            emitter.onComplete();
        });
    }

    private static void iterate(@NonNull View view, @NonNull ObservableEmitter<View> emitter) {
        emitter.onNext(view);
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                iterate(viewGroup.getChildAt(i), emitter);
            }
        }
    }

答案 7 :(得分:0)

具有枚举所有视图的小递归函数

 private fun processAllViews(viewGroup: ViewGroup) {
    for (child in viewGroup.children) {
        if (child is EditText) {
           // do some stuff with EditText
        } else if (child !is ViewGroup) {
            // do some stuff with not EditText and not ViewGroup
        } else {
            processAllViews(child as ViewGroup) // process inner layout
        }
    }
}

写在科特林。

要使用此功能:

processAllViews( [~rootLayoutId~] )

,或者如果您没有/不需要根布局ID

val baseContent = (findViewById<View>(android.R.id.content) as ViewGroup).getChildAt(0) as ViewGroup
processAllViews(baseContent)