안드로이드-View 안에 아이들을 넣습니까?


169

보기가 주어지면 그 안에 자식보기를 어떻게 얻을 수 있습니까?

그래서 사용자 정의보기가 있고 디버거 mChildren는 7 개의 다른보기가 있음을 보여줍니다 . 이러한 뷰에 액세스하는 방법이 필요하지만이를 수행하는 퍼블릭 API가없는 것 같습니다.

어떤 제안?

편집하다:

내 맞춤보기는 AdapterView

답변:


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

그럴까요?


2
이 작업을 재귀 적으로 수행하여 뷰 계층 JSON 객체를 생성하는 가장 좋은 방법은 무엇입니까?
jimbob

보기라는 부모 가정viewGroup
Prime624

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는 ViewGroup이 아닌 View 유형일 수 있으므로 getAllChildren의 재귀 호출은 캐스트가 실패함에 따라 예외를 일으킬 수 있습니다. 따라서 if (! (v instanceof ViewGroup)) 리턴을 추가해야합니다. 캐스트 전
Phil

2
작은 제안 : for 루프를 for (int i = 0, n = vg.getChildCount(); i < n; i++) Android로 바꾸면 메소드를 호출하는 대신 로컬 변수에 액세스하는 것이 훨씬 빠릅니다. 이런 식으로, 메소드는 뷰 그룹당 한 번만 호출 된 후 후속 실행시 로컬 변수가 사용됩니다.
ArtOfWarfare

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

내가 IDS에 액세스 할 수없는, UI를 코드를 통해 생성되고, 내가 할 수있는 일, 그래서 robotium를 사용하여 자동화를 쓰고는 제한된다
aryaxt

@ jonson, 모든 자녀를 가져야하는 경우 전혀 유용하지 않습니다.
Pacerier


17

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 다른 답변이 생성하는 인스턴스 있습니다. 또한 뷰 계층 구조의 수직 / 수평에 따라 결과가 달라질 수 있습니다.

게시자 : Android | ViewGroup의 모든 자식 요소 가져 오기


7

제안은 다음과 같습니다 . 주어진 이름 (예 :)을 사용하여 생성 된 ID(예 :로 지정 android:id="@+id/..My Str..)을 얻을 수 있습니다 . 메소드를 사용하는 코드 스 니펫 은 다음과 같습니다.RMy StrgetIdentifier()

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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.