Android:如何按类型查找视图

vmdwslir  于 2023-06-04  发布在  Android
关注(0)|答案(9)|浏览(276)

好了,我有一个类似于下面例子的布局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的孩子,但这只是一个视图。
什么是最好的方式得到一群孩子的类型?

eivgtgni

eivgtgni1#

这应该会让你走上正轨。

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) {
        ...
    }
}
wbrvyc0a

wbrvyc0a2#

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

ViewGroup vg = (ViewGroup)view;

想用就用如果你知道你将总是只使用一种类型的布局作为根容器,你可以强制转换为该类型,即:

LinearLayout vg = (LinearLayout)view;
dldeef67

dldeef673#

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)

vlurs2pr

vlurs2pr4#

您应该向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);
}
9vw9lbht

9vw9lbht5#

将根视图作为此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);
        }
    }
}
cyvaqqii

cyvaqqii6#

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

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;
}
ghg1uchk

ghg1uchk7#

类似@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);

感谢接受的回答。

t3psigkw

t3psigkw8#

简单的Kotlin代码(如果父节点是ViewGroup类型,例如LinearLayoutFrameLayout ...在您的例子中,LinearLayout也是ViewGroup的子类型。)

val button= view.children.first { it is Button }

如果它不止一个。

val buttons= view.children.filter { it is Button }
l3zydbqr

l3zydbqr9#

在我的自定义布局的情况下,所有的答案都不起作用。因为这些答案只检查子视图中的类是否存在,但是根视图本身可以是类。所以使用下面的代码解决了我的问题。

fun <T : View> ViewGroup.getViewsByType(tClass: Class<T>): List<T> {
    fun <T : View> ViewGroup.getSubViewsByType(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.getSubViewsByType(tClass))
                }
                if (tClass.isInstance(child))
                    add(tClass.cast(child))
            }
        }.filterNotNull()
    }
    return mutableListOf<T?>().apply {
        //Adding main view also if it is of the provided type
        if (tClass.isInstance(this@getViewsByType)) {
            add(tClass.cast(this@getViewsByType))
        }
        addAll(getSubViewsByType(tClass))
    }.filterNotNull()
}

活动中

val listOfViews=(binding.root as ViewGroup).getViewsByType(CustomLayout::class.java)

相关问题