Ответ 1
for(int index=0; index<((ViewGroup)viewGroup).getChildCount(); ++index) {
View nextChild = ((ViewGroup)viewGroup).getChildAt(index);
}
Будет ли это делать?
Учитывая представление, как я могу получить дочерние представления внутри него?
Итак, у меня есть собственный просмотр и отладчик, показывающий, что в mChildren
есть еще 7 видов.
Мне нужен способ доступа к этим представлениям, но похоже, что для этого существует публичный API.
любые предложения?
EDIT:
Мое пользовательское представление наследуется от AdapterView
for(int index=0; index<((ViewGroup)viewGroup).getChildCount(); ++index) {
View nextChild = ((ViewGroup)viewGroup).getChildAt(index);
}
Будет ли это делать?
Если вы не только хотите получить всех прямых детей, но и всех детей-детей и т.д., вы должны сделать это рекурсивно:
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");
}
Вы всегда можете получить доступ к дочерним представлениям через 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);
}
Я собираюсь предоставить этот ответ в качестве альтернативного рекурсивного алгоритма @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
Вот предложение: вы можете получить 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);
Чтобы обновить макет таблицы (TableLayout), мне пришлось использовать описанный выше рекурсивный подход, чтобы получить все дочерние дети и т.д.
Моя ситуация была несколько упрощена, потому что мне нужно было только работать с LinearLayout и те классы, которые были расширены от него, например TableLayout. И меня интересовали только дети TextView. Но я думаю, что это все еще применимо к этому вопросу.
Последний класс запускается как отдельный поток, что означает, что он может делать другие вещи в фоновом режиме до разбора для детей. Код маленький и простой и его можно найти в github: https://github.com/jkincali/Android-LinearLayout-Parser