Android-让孩子进入视图吗?


169

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

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

有什么建议?

编辑:

我的自定义视图继承自 AdapterView

Answers:



57

如果您不仅要获得所有直系子女,还要获得所有子女的子女,依此类推,则必须递归进行:

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

8
此调用不会保存,例如child可以是View类型,而不是ViewGroup类型,因此getAllChildren的递归调用可能会导致异常,因为强制转换失败。所以你应该添加一个if(!(v instanceof ViewGroup))return; 演员前
菲尔(Phil)

2
小建议:用for (int i = 0, n = vg.getChildCount(); i < n; i++) Android 替换for循环,在访问局部变量而不是调用方法时会更快。这样,每个视图组仅调用一次方法,然后在后续运行中使用局部变量。
ArtOfWarfare 2012年

由于Phil Diegmann的建议,我更改了代码。希望这可以帮助。为我工作。
IHeartAndroid

1
凉。我只建议添加一个布尔值“ includeViewGroups”,并且前提是它为true,即iewArrayList.add(v);。这对于在适配器中进行迭代很有用(而且我只需要叶子)。谢谢!
JRun

20

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

我无权访问ID,UI是通过代码生成的,我正在使用Robotium编写自动化程序,因此我只能做些事情
aryaxt 2011年

@jonson,如果您需要让所有孩子都没有用。
Pacerier '19


17

我将提供此答案,作为替代方法@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其他答案创建的新实例的数量最有关系。同样,结果可能会基于视图层次结构的垂直/水平程度而有所不同。

交叉发布自:Android | 获取ViewGroup的所有子元素


7

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


0

为了刷新表布局(TableLayout),我最终不得不使用上述的递归方法来获取所有子级的子级,依此类推。

我的情况有所简化,因为我只需要使用LinearLayout以及从中扩展的那些类(如TableLayout)。而且我只对找到TextView子项感兴趣。但是我认为它仍然适用于这个问题。

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


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;
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.