답변:
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로 바꾸면 메소드를 호출하는 대신 로컬 변수에 액세스하는 것이 훨씬 빠릅니다. 이런 식으로, 메소드는 뷰 그룹당 한 번만 호출 된 후 후속 실행시 로컬 변수가 사용됩니다.
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);
Kotlin을 사용하는 경우 2018 이후 에이 질문을 겪는 사람들을위한 업데이트로 Android KTX 확장 속성 ViewGroup.children 을 사용하여 View의 직계 자식 시퀀스를 얻을 수 있습니다.
테이블 레이아웃 (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;
}