web-dev-qa-db-ja.com

Android-ビュー内で子を取得しますか?

ビューを指定すると、その中の子ビューをどのように取得できますか?

そのため、カスタムビューがあり、デバッガーはmChildrenの下に7つの他のビューがあることを示しています。これらのビューにアクセスする方法が必要ですが、これを行うためのパブリックAPIがあるようには思えません。

助言がありますか?

編集:

カスタムビューはAdapterViewから継承します

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

それはしますか?

285

すべての直接の子供だけでなく、すべての子供の子供などを取得する場合は、再帰的に実行する必要があります。

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

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);
}
17
jonson

ビュー階層内のすべての子Viewsを検出するための代替@IHeartAndroidの再帰アルゴリズムとして、この答えを提供するだけです。この記事の執筆時点では、再帰的ソリューションには欠陥があり、結果に重複が含まれることに注意してください。

再帰を回避するのに苦労している人のために、ここに非再帰的な選択肢があります。これを実現するためのボーナスポイントは、再帰的ソリューションのdepth-firstアプローチに代わるbreadth-first検索代替でもあります。

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のすべての子要素を取得

14
MH.

提案は次のとおりです。特定の名前(Android:id="@+id/..My Str..など)を使用してIDによって生成された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
vanangelov

テーブルレイアウト(TableLayout)を更新するには、上記の再帰的アプローチを使用して、すべての子の子などを取得する必要がありました。

私の状況はやや単純化されました。なぜなら、LinearLayoutと、TableLayoutなどのそれから拡張されたクラスで作業する必要があるからです。そして、私はTextViewの子を見つけることにのみ興味がありました。しかし、この質問にはまだ適用できると思います。

最後のクラスは個別のスレッドとして実行されます。つまり、子を解析する前にバックグラウンドで他のことを実行できます。コードは小さくシンプルで、githubで見つけることができます: https://github.com/jkincali/Android-LinearLayout-Parser

0
jkincali