Answers:
for(int index = 0; index < ((ViewGroup) viewGroup).getChildCount(); index++) {
View nextChild = ((ViewGroup) viewGroup).getChildAt(index);
}
可以吗?
viewGroup
如果您不仅要获得所有直系子女,还要获得所有子女的子女,依此类推,则必须递归进行:
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");
}
for (int i = 0, n = vg.getChildCount(); i < n; i++)
Android 替换for循环,在访问局部变量而不是调用方法时会更快。这样,每个视图组仅调用一次方法,然后在后续运行中使用局部变量。
您始终可以通过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
视图层次结构中的所有child 。请注意,在撰写本文时,递归解决方案存在缺陷,因为它将在结果中包含重复项。
对于那些难以绕过递归的人来说,这是一种非递归的选择。您将获得奖励积分,因为意识到这也是递归解决方案的深度优先方法的广度优先搜索选择。
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
其他答案创建的新实例的数量最有关系。同样,结果可能会基于视图层次结构的垂直/水平程度而有所不同。
这里有一个建议:你可以得到的ID
(例如,指定由android:id="@+id/..My Str..
),通过产生R
通过使用其给定的名称(例如My Str
)。getIdentifier()
然后,使用方法的代码段将是:
public int getIdAssignedByR(Context pContext, String pIdString)
{
// Get the Context's 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);
作为针对在2018年之后遇到此问题的人的更新,如果您使用的是Kotlin,则只需使用Android KTX扩展属性ViewGroup.children即可获取View的直接子级序列。
为了刷新表布局(TableLayout),我最终不得不使用上述的递归方法来获取所有子级的子级,依此类推。
我的情况有所简化,因为我只需要使用LinearLayout以及从中扩展的那些类(如TableLayout)。而且我只对找到TextView子项感兴趣。但是我认为它仍然适用于这个问题。
最终类作为单独的线程运行,这意味着它可以在解析子级之前在后台执行其他操作。该代码又小又简单,可以在github上找到:https : //github.com/jkincali/Android-LinearLayout-Parser