17

好的,所以我有一个类似于以下示例的布局 xml:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/tile_bg" >

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingTop="10dp" >

    <LinearLayout
        android:id="@+id/layout_0"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <!-- view stuff here -->
    </LinearLayout>

    <!-- more linear layouts as siblings to this one -->

</LinearLayout>

实际上,我有大约 7 个 LinearLayout 项目,每个项目的 id 从 layout_0 等开始增加。我希望能够掌握根 LinearLayout 下的所有 LinearLayout 项目。我是否需要在根目录上放置一个 id 并通过 id 找到所有其他人,或者我可以按类型获取它们。

我用来膨胀布局的代码是:

View view = (View) inflater.inflate(R.layout.flight_details, container, false);

我在某处读到您可以迭代 ViewGroup 的子级,但这只是一个视图。

按类型获得一堆孩子的最佳方法是什么?

4

7 回答 7

34

这应该让你走上正确的轨道。

LinearLayout rootLinearLayout = (LinearLayout) findViewById(R.id.rootLinearLayout);
int count = rootLinearLayout.getChildCount();
for (int i = 0; i < count; i++) {
    View v = rootLinearLayout.getChildAt(i);
    if (v instanceof LinearLayout) {
        ...
    }
}
于 2012-12-14T22:19:01.483 回答
3

ViewGroup如果您知道布局的根元素是任何子类LinearLayout或其他布局,则可以安全地将结果视图转换为:

ViewGroup vg = (ViewGroup)view;

并根据需要使用。如果您知道您将始终只对根容器使用一种类型的布局,则可以强制转换为该类型,即:

LinearLayout vg = (LinearLayout)view;
于 2012-12-14T22:25:12.440 回答
1

您应该向 LinearLayout 根添加一个 id:

<LinearLayout
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:paddingTop="10dp" >

    <LinearLayout
        android:id="@+id/layout_0"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <!-- view stuff here -->
    </LinearLayout>

    <!-- more linear layouts as siblings to this one -->

</LinearLayout>

然后像往常一样膨胀整个布局:

View view = (View) inflater.inflate(R.layout.flight_details, container, false);

抓住你的根LinearLayout

LinearLayout root = (LinearLayout) view.findViewById(R.id.root);

LinearLayout[] children = new LinearLayout[root.getChildCount()];

for (int i = 0; i < root.getChildCount(); i++) {
    children[i] = (LinearLayout) root.getChildAt(i);
}
于 2012-12-14T22:22:20.177 回答
1

将根视图作为此 DFS 方法的参数传递:

private List<LinearLayout> mArr = new ArrayList<LinearLayout>();

private void getLinearLayouts(ViewGroup parent) {
    int childCount = parent.getChildCount();
    for (int i = 0; i < childCount; i++) {
        View child = parent.getChildAt(i);
        if (child instanceof ViewGroup) {
            getLinearLayouts((ViewGroup) child);
            if (child instanceof LinearLayout)
                mArr.add((LinearLayout) child);
        }
    }
}
于 2012-12-14T22:23:33.077 回答
1

我只是想添加一个更通用的方法,但您必须记住,这样做是一种繁重的方法。

无论如何,这是代码:

private static <T extends View> ArrayList<T> getChildrenOfParentWithClass(ViewGroup parent, Class<T> clazz)
{
    ArrayList<T> children = new ArrayList<>();

    int childCount = parent.getChildCount();
    for (int i = 0; i < childCount; i++)
    {
        View child = parent.getChildAt(i);
        if (child instanceof ViewGroup)
        {
            children.addAll(getChildrenOfParentWithClass((ViewGroup) child, clazz));
            if (child.getClass().equals(clazz))
            {
                children.add((T) child);
            }
        }
    }

    return children;
}
于 2017-03-23T14:40:22.390 回答
1

Kotlin 版本的 Mir-Ismaili 回答:

fun <T : View> ViewGroup.getViewsByType(tClass: Class<T>): List<T> {
  return mutableListOf<T?>().apply {
    for (i in 0 until childCount) {
      val child = getChildAt(i)
      (child as? ViewGroup)?.let {
        addAll(child.getViewsByType(tClass))
      }
      if (tClass.isInstance(child))
        add(tClass.cast(child))
    }
  }.filterNotNull()
}

例如调用它:myViewGroup.getViewsByType(EditText::class.java)

于 2019-03-12T15:30:32.363 回答
0

就像@ChristopheCVB 的回答一样,但也支持继承(参见tClass.isInstance(child))。

public static <T extends View> ArrayList<T> getViewsByType(ViewGroup root, Class<T> tClass) {
    final ArrayList<T> result = new ArrayList<>();
    int childCount = root.getChildCount();
    for (int i = 0; i < childCount; i++) {
        final View child = root.getChildAt(i);
        if (child instanceof ViewGroup)
            result.addAll(getViewsByType((ViewGroup) child, tClass));

        if (tClass.isInstance(child))
            result.add(tClass.cast(child));
    }
    return result;
}

以及一个简单的用法示例:

ArrayList<TextView> TextViews = getViewsByType(rootLayout, TextView.class);

感谢接受的答案。

于 2017-08-20T15:22:40.067 回答