有没有办法遍历Activity中的所有视图?类似的东西:
Iterator it = getViewIterator();
...
这根本存在吗?
答案 0 :(得分:17)
如果您的所有观看次数都在LinearLayout
或container
扩展ViewGroup
,那么您可以使用getChildCount()
和getChildAt(int)
这两个函数进行迭代所有的
载有意见。
希望这有帮助。
答案 1 :(得分:8)
假设“您的活动中的所有视图”是指层次结构中的每个视图,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);
答案 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)