Android - çocukları bir Görünümün içine mi sokuyorsunuz?


169

Bir Görünüm verildiğinde çocuğun görüşlerini nasıl alabilirim?

Bu yüzden özel bir Görünüm var ve hata ayıklayıcı altında mChildren7 diğer görünümler olduğunu gösterir . Bu görünümlere erişmek için bir yol gerekir ama bunu yapmak için genel bir API gibi görünmüyor.

baska öneri?

DÜZENLE:

Özel görünümüm, AdapterView

Yanıtlar:


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

Olacak?


2
Bunu yinelemeli olarak yapmanın ve böylece bir görünüm heirarchy JSON nesnesi oluşturmanın en iyi yolu nedir?
jimbob

Üst görünümün adı viewGroup
verildiğini

57

Sadece doğrudan çocukları değil, tüm çocuk çocuklarını vb. Almak istiyorsanız, bunu tekrar tekrar yapmanız gerekir:

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

Sonucu kullanmak için şöyle bir şey yapabilirsiniz:

    // 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
Bu çağrı kaydedilmez; örneğin, alt öğe ViewGroup türünde değil ViewGroup türünde olabilir, dolayısıyla getAllChildren yinelemeli çağrısı, döküm başarısız olduğunda istisnaya neden olabilir. Bu yüzden bir if (! (V instanceof ViewGroup)) dönüşü eklemelisiniz; oyuncu kadrosu öncesi
Phil

2
Küçük öneri: for döngünüzü for (int i = 0, n = vg.getChildCount(); i < n; i++) Android'de değiştirin, yöntem çağırmak yerine yerel değişkenlere erişmek çok daha hızlı olur. Bu şekilde, bir yöntem her görüntüleme grubu için yalnızca bir kez çağrılır ve daha sonraki çalıştırmalarda yerel bir değişken kullanılır.
ArtOfWarfare

Phil Diegmann'ın önerisi nedeniyle kodu değiştirdim. Bu yardımcı olur umarım. Benim için çalışıyor.
IHeartAndroid

1
Güzel. Ben sadece bir boolean 'includeViewGroups' eklemeyi öneririm ve sadece doğruysa, iewArrayList.add (v); Bu bir Adaptörde yineleme için yararlıdır (ve sadece yapraklara ihtiyacım var). Teşekkürler!
JRun

20

Alt görünümlere her zaman View.findViewById () http://developer.android.com/reference/android/view/View.html#findViewById(int ) aracılığıyla erişebilirsiniz .

Örneğin, bir etkinlik / görünüm içinde:

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

veya bir görünüme referansınız varsa:

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

Kimliklere erişimim yok, kullanıcı arayüzü kodla oluşturuluyor, robotium kullanarak otomasyon yazıyorum, bu yüzden yapabileceğim şeyler sınırlı
aryaxt

@jonson, tüm çocukları almanız gerekiyorsa hiç kullanışlı değil.
Pacerier


17

Bu cevabı sadece Viewbir görünüm hiyerarşisinde tüm çocukları keşfetmek için @ IHeartAndroid'in özyinelemeli algoritması olarak sunacağım . Bu yazı yazılırken, özyinelemeli çözümün, sonuçta kopyalar içereceği için kusurlu olduğunu unutmayın.

Başlarını özyineleme etrafına sarmakta zorlananlar için, burada özyinelemesiz bir alternatif. Bunun , özyinelemeli çözümün derinlik-ilk yaklaşımına bir genişlik ilk arama alternatifi olduğunu fark ettiğiniz için bonus puanlar alırsınız .

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

Birkaç hızlı test (resmi olmayan hiçbir şey), bu alternatifin de daha hızlı olduğunu düşündürmektedir, ancak bunun ArrayListdiğer cevabın yarattığı yeni örneklerin sayısıyla ilgili olması muhtemeldir . Ayrıca, sonuçlar görünüm hiyerarşisinin ne kadar dikey / yatay olduğuna bağlı olarak değişebilir.

Yayınlandığı tarih: Android | Bir ViewGroup öğesinin tüm alt öğelerini alma


7

İşte bir öneri: verilen adı (örneğin ) kullanarak oluşturulan ID(örneğin tarafından belirtilen ) alabilirsiniz. Bu durumda yöntemi kullanan bir kod snippet'i şöyle olur: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;
}

Bir içinden Activity, örnek bir kullanımla birlikte 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

Bir masa düzenini (TableLayout) yenilemek için, yukarıda belirtilen tüm çocukların çocuklarını ve benzerlerini elde etmek için tekrarlanan yaklaşımı kullanmak zorunda kaldım.

Benim durumum biraz basitleştirildi çünkü sadece LinearLayout ile çalışmam gerekiyordu ve bu sınıflar TableLayout gibi genişledi. Ve sadece TextView çocuklarını bulmakla ilgileniyordum. Ama bence bu soru için hala geçerli.

Son sınıf ayrı bir iş parçacığı olarak çalışır, yani çocuklar için ayrıştırmadan önce arka planda başka şeyler yapabilir. Kod küçük ve basittir ve github'da bulunabilir: https://github.com/jkincali/Android-LinearLayout-Parser


0

Bu yöntem bir düzen içindeki tüm görünümleri alır, bu Alexander Kulyakhtin'in cevabına benzer. Fark, her tür üst düzen kabul eder ve bir Array List listesi döndürür.

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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.