回答:
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で置き換えると、メソッドを呼び出す代わりにローカル変数にアクセスする方がはるかに高速になる傾向があります。このように、メソッドはビューグループごとに1回だけ呼び出され、その後の実行ではローカル変数が使用されます。
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);
}
この回答View
は、ビュー階層内のすべての子を検出するための@IHeartAndroidの再帰アルゴリズムの代替として提供します。この記事の執筆時点では、再帰的なソリューションには欠陥があり、結果に重複が含まれることに注意してください。
再帰に頭を悩ませるのに苦労している人のために、非再帰的な代替案があります。これが再帰的ソリューションの深さ優先アプローチの幅優先検索の代替手段であることを理解すると、ボーナスポイントを獲得できます。
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を使用して、ビューの直接の子のシーケンスを取得できます。
テーブルレイアウト(TableLayout)を更新するために、私は上記の再帰的なアプローチを使用してすべての子の子などを取得する必要がありました。
LinearLayoutとそれから拡張されたTableLayoutなどのクラスを使用するだけでよいので、状況は多少単純化されました。そして、私はTextViewの子供を見つけることにのみ興味がありました。しかし、私はそれがこの質問にまだ当てはまると思います。
最後のクラスは別のスレッドとして実行されます。つまり、子の解析前にバックグラウンドで他のことを実行できます。コードは小さくてシンプルで、githubにあります:https : //github.com/jkincali/Android-LinearLayout-Parser
このメソッドは、レイアウト内のすべてのビューを取得します。これは、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;
}