Android - đưa trẻ em vào Chế độ xem?


169

Đưa ra một View làm thế nào tôi có thể có được các khung nhìn con bên trong nó?

Vì vậy, tôi có Chế độ xem và trình gỡ lỗi tùy chỉnh cho thấy bên dưới mChildrencó 7 chế độ xem khác. Tôi cần một cách để truy cập các chế độ xem này nhưng có vẻ như không có API công khai để thực hiện việc này.

bất kỳ đề xuất?

BIÊN TẬP:

Chế độ xem tùy chỉnh của tôi kế thừa từ AdapterView

Câu trả lời:


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

Điều đó sẽ làm gì?


2
Cách tốt nhất để làm điều này một cách đệ quy và từ đó tạo ra một đối tượng JSON bá đạo?
jimbob

Giả sử Chế độ xem chính được đặt tênviewGroup
Prime624

57

Nếu bạn không chỉ muốn có được tất cả trẻ em trực tiếp mà tất cả trẻ em của trẻ em, v.v., bạn phải làm điều đó một cách đệ quy:

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

Để sử dụng kết quả, bạn có thể làm một cái gì đó như thế này:

    // 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
Cuộc gọi này không được lưu, ví dụ như đứa trẻ có thể thuộc kiểu View chứ không phải của Viewgroup, vì vậy cuộc gọi đệ quy của getAllChildren có thể gây ra ngoại lệ, vì việc truyền không thành công. Vì vậy, bạn nên thêm trả về if (! (V instanceof Viewgroup)); trước dàn diễn viên
Phil

2
Gợi ý nhỏ: thay thế vòng lặp for của bạn bằng for (int i = 0, n = vg.getChildCount(); i < n; i++) Trên Android, truy cập các biến cục bộ thay vì gọi một phương thức có xu hướng nhanh hơn nhiều. Theo cách này, một phương thức chỉ được gọi một lần cho mỗi nhóm xem và sau đó trong các lần chạy tiếp theo, một biến cục bộ được sử dụng.
ArtOfWarfare

Tôi đã thay đổi mã vì gợi ý của Phil Diegmann. Hi vọng điêu nay co ich. Làm việc cho tôi.
IHeartAndroid

1
Mát mẻ. Tôi chỉ đề nghị thêm một boolean 'includeViewgroup' và chỉ khi nó đúng, iewArrayList.add (v); Điều này rất hữu ích cho việc lặp lại trong Bộ điều hợp (và tôi chỉ cần các lá). Cảm ơn!
JRun

20

Bạn luôn có thể truy cập các chế độ xem con qua View.findViewById () http://developer.android.com/reference/android/view/View.html#findViewById(int ).

Ví dụ: trong một hoạt động / chế độ xem:

...
private void init() {
  View child1 = findViewById(R.id.child1);
}
...

hoặc nếu bạn có một tham chiếu đến một khung nhìn:

...
private void init(View root) {
  View child2 = root.findViewById(R.id.child2);
}

Tôi không có quyền truy cập vào id, giao diện người dùng được tạo thông qua mã, tôi đang viết tự động hóa bằng robot, vì vậy những điều tôi có thể làm bị hạn chế
aryaxt

@jonson, không hữu ích chút nào nếu bạn cần có tất cả trẻ em.
Pacerier


17

Tôi sẽ chỉ cung cấp câu trả lời này như là một thuật toán đệ quy thay thế của @ IHeartAndroid để khám phá tất cả các con Viewtrong một hệ thống phân cấp xem. Lưu ý rằng tại thời điểm viết bài này, giải pháp đệ quy bị thiếu sót ở chỗ nó sẽ chứa các bản sao trong kết quả của nó.

Đối với những người gặp khó khăn trong việc điều chỉnh đệ quy, đây là một giải pháp thay thế không đệ quy. Bạn nhận được điểm thưởng khi nhận ra đây cũng là một thay thế tìm kiếm đầu tiên theo chiều rộng cho phương pháp tiếp cận theo chiều sâu của giải pháp đệ quy.

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

Một vài thử nghiệm nhanh (không có gì chính thức) cho thấy sự thay thế này cũng nhanh hơn, mặc dù điều đó rất có thể xảy ra với số lượng phiên bản mới ArrayListmà câu trả lời khác tạo ra. Ngoài ra, kết quả có thể thay đổi dựa trên cách phân cấp chế độ xem dọc / ngang.

Đăng chéo từ: Android | Nhận tất cả các phần tử con của Viewgroup


7

Đây là một gợi ý: bạn có thể lấy ID(được chỉ định bởi android:id="@+id/..My Str..) được tạo bằng Rcách sử dụng tên đã cho (ví dụ My Str). Một đoạn mã sử dụng getIdentifier()phương thức sau đó sẽ là:

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

Từ trong một Activity, một ví dụ sử dụng cùng với findViewByIdsẽ là:

// Get the View (e.g. a TextView) which has the Layout ID of "UserInput"
int rID = getIdAssignedByR(this, "UserInput")
TextView userTextView = (TextView) findViewById(rID);

3

Là một bản cập nhật cho những người gặp phải câu hỏi này sau năm 2018, nếu bạn đang sử dụng Kotlin, bạn chỉ cần sử dụng thuộc tính tiện ích mở rộng Android KTX Viewgroup.children để nhận một chuỗi các con ngay lập tức của View.


0

Để làm mới bố cục bảng (TableLayout), cuối cùng tôi đã phải sử dụng phương pháp đệ quy được đề cập ở trên để có được tất cả trẻ em của trẻ em và vv.

Tình hình của tôi đã được đơn giản hóa một chút vì tôi chỉ cần làm việc với linearLayout và các lớp được mở rộng từ nó như TableLayout. Và tôi chỉ quan tâm đến việc tìm kiếm trẻ em TextView. Nhưng tôi nghĩ nó vẫn có thể áp dụng cho câu hỏi này.

Lớp cuối cùng chạy như một luồng riêng biệt, có nghĩa là nó có thể làm những việc khác trong nền trước khi phân tích cú pháp cho trẻ em. Mã này nhỏ và đơn giản và có thể tìm thấy tại github: https://github.com/jkincali/Android-LinearLayout-Parser


0

Phương pháp này có tất cả các khung nhìn bên trong một bố cục, điều này tương tự như câu trả lời của Alexander Kulyakhtin. Sự khác biệt là, nó chấp nhận bất kỳ kiểu bố trí cha mẹ nào và trả về một Danh sách các khung nhìn.

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.