安卓系统——让孩子进入视图?

给定一个视图,我如何才能得到子视图内?

所以我有一个自定义的视图和调试器显示,在 mChildren下有7个其他的视图。 我需要一种访问这些视图的方法,但似乎没有公共 API 来实现这一点。

有什么建议吗?

编辑:

我的自定义视图继承自 AdapterView

202137 次浏览

您总是可以通过 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);
}
for(int index = 0; index < ((ViewGroup) viewGroup).getChildCount(); index++) {
View nextChild = ((ViewGroup) viewGroup).getChildAt(index);
}

可以吗?

这里有一个建议: 你可以得到 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);

如果你不仅想得到所有的直接子女,而且想得到所有子女的子女等等,你必须递归地做:

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

我将提供这个答案作为@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 的所有子元素

为了刷新表格布局(TableLayout) ,我最终不得不使用上面提到的递归方法来获取所有子元素等等。

我的情况有些简单,因为我只需要使用 LinearLayout 和那些从它扩展的类,比如 TableLayout。我只对寻找 TextView 的孩子感兴趣。但我认为它仍然适用于这个问题。

最后一个类作为一个单独的线程运行,这意味着它可以在为子类解析之前在后台执行其他操作。代码很小,很简单,可以在 github: https://github.com/jkincali/Android-LinearLayout-Parser找到

这种方法在一个布局中获取所有视图,这与亚历山大 · 库利亚赫金的回答类似。区别在于,它接受任何类型的父布局并返回视图的 Array List。

public List<View> getAllViews(ViewGroup layout){
List<View> views = new ArrayList<>();
for(int i =0; i< layout.getChildCount(); i++){
views.add(layout.getChildAt(i));
}
return views;
}

对于那些在2018年之后遇到这个问题的人来说,如果你正在使用 Kotlin,你可以简单地使用 安卓 KTX扩展属性 ViewGroup.children来获得视图的直接子序列。