Android - получить детей внутри представления?

Учитывая представление, как я могу получить дочерние представления внутри него?

Итак, у меня есть собственный просмотр и отладчик, показывающий, что в mChildren есть еще 7 видов. Мне нужен способ доступа к этим представлениям, но похоже, что для этого существует публичный API.

любые предложения?

EDIT:

Мое пользовательское представление наследуется от AdapterView

Ответ 1

for(int index=0; index<((ViewGroup)viewGroup).getChildCount(); ++index) {
    View nextChild = ((ViewGroup)viewGroup).getChildAt(index);
}

Будет ли это делать?

Ответ 2

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

private ArrayList<View> getAllChildren(View v) {

    if (!(v instanceof ViewGroup)) {
        ArrayList<View> viewArrayList = new ArrayList<View>();
        viewArrayList.add(v);
        return viewArrayList;
    }

    ArrayList<View> result = new ArrayList<View>();

    ViewGroup vg = (ViewGroup) v;
    for (int i = 0; i < vg.getChildCount(); i++) {

        View child = vg.getChildAt(i);

        ArrayList<View> viewArrayList = new ArrayList<View>();
        viewArrayList.add(v);
        viewArrayList.addAll(getAllChildren(child));

        result.addAll(viewArrayList);
    }
    return result;
}

Чтобы использовать результат, вы можете сделать что-то вроде этого:

    // check if a child is set to a specific String
    View myTopView;
    String toSearchFor = "Search me";
    boolean found = false;
    ArrayList<View> allViewsWithinMyTopView = getAllChildren(myTopView);
    for (View child : allViewsWithinMyTopView) {
        if (child instanceof TextView) {
            TextView childTextView = (TextView) child;
            if (TextUtils.equals(childTextView.getText().toString(), toSearchFor)) {
                found = true;
            }
        }
    }
    if (!found) {
        fail("Text '" + toSearchFor + "' not found within TopView");
    }

Ответ 3

Вы всегда можете получить доступ к дочерним представлениям через View.findViewById() http://developer.android.com/reference/android/view/View.html#findViewById(int).

Например, в действии/представлении:

...
private void init() {
  View child1 = findViewById(R.id.child1);
}
...

или если у вас есть ссылка на представление:

...
private void init(View root) {
  View child2 = root.findViewById(R.id.child2);
}

Ответ 4

Я собираюсь предоставить этот ответ в качестве альтернативного рекурсивного алгоритма @IHeartAndroid для обнаружения всего дочернего View в иерархии представлений. Обратите внимание, что на момент написания статьи рекурсивное решение имеет недостатки, поскольку оно будет содержать дубликаты в его результате.

Для тех, у кого есть проблемы, обертывание головы вокруг рекурсии, здесь нерекурсивная альтернатива. Вы получаете бонусные баллы за то, что понимаете, что это также альтернативный вариант поиска в глубину, основанный на глубине первого рекурсивного решения.

private List<View> getAllChildrenBFS(View v) {
    List<View> visited = new ArrayList<View>();
    List<View> unvisited = new ArrayList<View>();
    unvisited.add(v);

    while (!unvisited.isEmpty()) {
        View child = unvisited.remove(0);
        visited.add(child);
        if (!(child instanceof ViewGroup)) continue;
        ViewGroup group = (ViewGroup) child;
        final int childCount = group.getChildCount();
        for (int i=0; i<childCount; i++) unvisited.add(group.getChildAt(i));
    }

    return visited;
}

Несколько быстрых тестов (ничего формального) говорят о том, что эта альтернатива также быстрее, хотя это, скорее всего, связано с количеством новых экземпляров ArrayList, создаваемых другим ответом. Кроме того, результаты могут варьироваться в зависимости от вертикальной/горизонтальной иерархии представлений.

Отправлено от: Android | Получить все дочерние элементы ViewGroup

Ответ 5

Вот предложение: вы можете получить ID (указанный, например, android:id="@+id/..My Str..), который был сгенерирован R, используя его имя (например, My Str). Фрагмент кода, использующий метод getIdentifier(), будет следующим:

public int getIdAssignedByR(Context pContext, String pIdString)
{
    // Get the Context Resources and Package Name
    Resources resources = pContext.getResources();
    String packageName  = pContext.getPackageName();

    // Determine the result and return it
    int result = resources.getIdentifier(pIdString, "id", packageName);
    return result;
}

Внутри Activity пример использования в сочетании с findViewById будет:

// Get the View (e.g. a TextView) which has the Layout ID of "UserInput"
int rID = getIdAssignedByR(this, "UserInput")
TextView userTextView = (TextView) findViewById(rID);

Ответ 6

Чтобы обновить макет таблицы (TableLayout), мне пришлось использовать описанный выше рекурсивный подход, чтобы получить все дочерние дети и т.д.

Моя ситуация была несколько упрощена, потому что мне нужно было только работать с LinearLayout и те классы, которые были расширены от него, например TableLayout. И меня интересовали только дети TextView. Но я думаю, что это все еще применимо к этому вопросу.

Последний класс запускается как отдельный поток, что означает, что он может делать другие вещи в фоновом режиме до разбора для детей. Код маленький и простой и его можно найти в github: https://github.com/jkincali/Android-LinearLayout-Parser