Подтвердить что ты не робот

Android: как найти виды по типу

Итак, у меня есть макет 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 или я могу получить их по типу.

Код, который я использую для раздувания макета:

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

Я где-то читал, что вы можете перебирать детей из ViewGroup, но это только вид.

Каков наилучший способ получить кучу детей по типу?

4b9b3361

Ответ 1

Это должно привести вас к правильному пути.

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

Ответ 2

Вы можете безопасно отбросить представление результата до ViewGroup, если знаете, что ваш корневой элемент макета - это любой подкласс типа LinearLayout или другие макеты:

ViewGroup vg = (ViewGroup)view;

и используйте, как хотите. Если вы знаете, что всегда используйте только один тип макета для корневого контейнера, вы можете применить его к типу, то есть:

LinearLayout vg = (LinearLayout)view;

Ответ 3

Вы должны добавить id к корню LinearLayout:

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

Ответ 4

Передайте корневой вид в качестве аргумента для этого метода 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);
        }
    }
}

Ответ 5

Я просто хотел добавить более общий, но вы должны иметь в виду, что это тяжелый подход для этого.

В любом случае, вот код:

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

Ответ 6

Как и @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);

Благодарим принятый ответ.