有没有一种方法可以遍历所有的Activity中的视图?就像这样:
Iterator it = getViewIterator();
...
这种方法是否存在?
有没有一种方法可以遍历所有的Activity中的视图?就像这样:
Iterator it = getViewIterator();
...
这种方法是否存在?
LinearLayout
或其他扩展了ViewGroup
的容器
中,您可以使用getChildCount()
和getChildAt(int)
函数并遍历所有包含的视图。希望这有所帮助。假设您所说的“Activity中所有视图”是指整个层次结构中的每个视图,那么在Android中没有任何Iterator
或其他允许您迭代所有视图的东西。
ViewGroup
有getChildCount
和getChildAt
方法,但它们仅适用于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);
以下是我根据Harry Joy的答案编写的示例。它遍历父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;
}
Activity通常包含一个主要的布局容器,其中放置了所有其他视图。 使用主布局容器的引用。遍历其子项(使用getChild(position),getchildcount()等),如果任何子项本身是容器,则在其上应用相同的函数。这有点像遍历树形结构。
一个小的递归函数,用于枚举所有视图
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
}
}
}
使用 Kotlin 编写。
要使用此函数:
processAllViews( [~rootLayoutId~] )
或者如果您没有/不想要根布局 ID
val baseContent = (findViewById<View>(android.R.id.content) as ViewGroup).getChildAt(0) as ViewGroup
processAllViews(baseContent)
RxJava 解决方案
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);
}
}
}
如果你真的需要一个迭代器,API 中没有类似的东西可用。你将不得不编写自己的迭代器,建立在 Harry Joy 和 Javanator 建议的逻辑之上。
如果你想避免丑陋的 for (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))