Android - 让孩子进入视图?

时间:2011-12-06 03:59:59

标签: android view

给定一个视图如何在其中获取子视图?

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

有什么建议吗?

修改

我的自定义视图继承自AdapterView

8 个答案:

答案 0 :(得分:285)

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

那会吗?

答案 1 :(得分:54)

如果你不仅想要所有直接的孩子,而是所有孩子的孩子,等等,你必须递归地做:

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

答案 2 :(得分:17)

您始终可以通过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);
}

答案 3 :(得分:14)

我将提供此答案作为替代@ 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 | Get all children elements of a ViewGroup

答案 4 :(得分:5)

以下是一条建议:您可以使用{1}}使用其给定名称(例如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);

答案 5 :(得分:3)

作为对在2018年之后遇到此问题的人的更新,如果您使用的是Kotlin,则可以简单地使用Android KTX扩展属性ViewGroup.children来获取View的直接子级序列。 / p>

答案 6 :(得分:0)

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

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

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

答案 7 :(得分:0)

此方法采用布局内的所有视图,这与Alexander Kulyakhtin的答案类似。不同之处在于,它接受任何类型的父布局并返回视图的数组列表。

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