Belirtilen alt öğenin zaten bir üst öğesi var. Önce çocuğun üst öğesinde removeView () öğesini çağırmalısınız (Android)


164

Sık sık iki düzen arasında geçiş yapmak zorundayım. Hata, aşağıda yayınlanan düzende gerçekleşiyor.

Düzenim ilk kez çağrıldığında herhangi bir hata oluşmaz ve her şey yolundadır. Daha sonra farklı bir düzen (boş bir düzen) çağırdığımda ve daha sonra düzenimi ikinci kez çağırdığımda, aşağıdaki hatayı atar:

> FATAL EXCEPTION: main
>     java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

Düzen kodum şöyle:

    tv = new TextView(getApplicationContext()); // are initialized somewhere else
    et = new EditText(getApplicationContext()); // in the code


private void ConsoleWindow(){
        runOnUiThread(new Runnable(){

     @Override
     public void run(){

        // MY LAYOUT:
        setContentView(R.layout.activity_console);
        // LINEAR LAYOUT
        LinearLayout layout=new LinearLayout(getApplicationContext());
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout);

        // TEXTVIEW
        layout.addView(tv); //  <==========  ERROR IN THIS LINE DURING 2ND RUN
        // EDITTEXT
        et.setHint("Enter Command");
        layout.addView(et);
        }
    }
}

Bu sorunun daha önce sorulduğunu biliyorum, ama benim durumumda yardımcı olmadı.


1
Yalnızca aynı hatayı alan biri için: Doğru öğeyi eklediğinizden emin olun. Diyelim ki eklemelisiniz LinearLayoutama ekliyorsunuz TextView. Yani düzeltin.
Geliştirici

android databinding kullanırken 'root' id ile görünüm ilan etmemelisiniz, aynı hataya neden olur.
Mohammad Reza Khahani

kullananlar için TranstitionManager.beginDelayedTransitionlütfen cevabımı
mochadwi

Yanıtlar:


354

Hata mesajı ne yapmanız gerektiğini söyler.

// TEXTVIEW
if(tv.getParent() != null) {
    ((ViewGroup)tv.getParent()).removeView(tv); // <- fix
}
layout.addView(tv); //  <==========  ERROR IN THIS LINE DURING 2ND RUN
// EDITTEXT

57

sadece attachtoroot argümanını false olarak ilet

View view = inflater.inflate(R.layout.child_layout_to_merge, parent_layout, false);

2
Benim için bu bir boğa gözüydü. RecycleView öğesindeki sınırlama düzeni, çalışma zamanına göre kısıtlamaları dinamik olarak değiştirir. ConstraintSet.apply, bu kadar, işe yaramadı. Bu nedenle, üst öğeyi onCreateViewHolder'da yayın, ancak şişirmeye ek param olarak yanlış gönderin.
miroslavign

3
Bu doğru çözüm! @Sniper'ın dediği gibi, ikinci parametreye null değerinin geçmesi, çocuk görüşünün kendisini ebeveynine olması gerektiği gibi hizalamamasına neden olabilir. Üst öğeyi geçen OTOH, söz konusu hataya neden olabilir. Yani, attachToRoot= false, giden yol budur.
Vassilis

Doğru yapmanın yolu.
Rowland Mtetezi

50

Burada benim recyclerview ile hata arama geldi ama çözüm (tabii ki) işe yaramadı. Geri dönüşüm izleme durumunda sebebini ve çözümünü yazdım. Umarım birine yardımcı olur.

onCreateViewHolder()Aşağıdaki yöntem izlenirse hata oluşur :

layoutInflater = LayoutInflater.from(context);
return new VH(layoutInflater.inflate(R.layout.single_row, parent));

Bunun yerine olmalı

return new VH(layoutInflater.inflate(R.layout.single_row, null));

15
Bazen tam olarak sorulan soruların cevapları olmayan rastgele cevaplar başka birine yardımcı olur. Bu benim için çalıştı. Teşekkürler!
Ajith Memana

1
Güzel! Ve bu yüzden insanlar çoğunlukla inflatörlerde 2d parametreleri olarak "null" u geçmelidir. Teşekkürler.
superUser

4
Üst öğeden sorumlu parametreye Null iletmek kötü bir fikir değildir, ancak bu durumda çocuk görüşünün (şişirdiğiniz) bazı durumlarda kendini doğru şekilde ölçemeyeceğini bilmelisiniz, çünkü ebeveyn hakkında bir şey bilmek. Bazı durumlarda işe yarayacaktır, ancak bazılarında işe yaramayacaktır.
Stoycho Andreev

1
Bunun, izleyici temasının doğru şekilde çözülmemesine neden olabileceğini unutmayın.
SpaceBison

13

Bu mesajı yanlış yerine true kök yerine ekleme kullanarak bir parça işlemeye çalışırken aldım :

return inflater.inflate(R.layout.fragment_profile, container, true)

Yaptıktan sonra:

return inflater.inflate(R.layout.fragment_profile, container, false)

İşe yaradı.


5

Başka bir çözüm aşağıdaki gibi çalışmıyorsa:

View view = inflater.inflate(R.layout.child_layout_to_merge, parent_layout, false);

onCreateView parçasından ne döndürdüğünüzü kontrol edin tekli görünüm mü yoksa görünüm grubu mu? benim durumumda parçası xml kök üzerinde viewpager vardı ve ben viewpager iade edildi, ben viewgroup düzeni ekledi zaman ben viewpager (view) değil, şimdi viewgroup dönmek zorunda güncellenmedi.


5

frameLayout.addView (bannerAdView); <----- Bu satırda hata alırsanız aşağıdaki gibi yapın ..

if (bannerAdView.getParent() != null)

  ((ViewGroup) bannerAdView.getParent()).removeView(bannerAdView);

   frameLayout.addView(bannerAdView);     <------ now added view

4

Benim hatam görünümü şöyle tanımlamak oldu:

view = inflater.inflate(R.layout.qr_fragment, container);

Eksikti:

view = inflater.inflate(R.layout.qr_fragment, container, false);

3

Benim durumumda sorun, üst görünümden <merge>mizanpajla şişirilmiş olmamdan kaynaklanıyor . Bu durumda, addView()kazaya neden oldu.

View to_add = inflater.inflate(R.layout.child_layout_to_merge, parent_layout, true);
// parent_layout.addView(to_add); // THIS CAUSED THE CRASH

Kaldırmak addView()sorunun çözülmesine yardımcı oldu.


2

görünümü zaten ekleyip eklemediğinizi kontrol edin

if (textView.getParent() == null)
    layout.addView(textView);

2

Aşağıdaki kod benim için çözdü:

@Override
public void onDestroyView() {
    if (getView() != null) {
        ViewGroup parent = (ViewGroup) getView().getParent();
        parent.removeAllViews();
    }
    super.onDestroyView();
}

Not: Hata benim parça sınıfından ve onDestroy yöntemini bu şekilde geçersiz kılarak çözebilirim.



2

Benim durumumda, diğer görünüme ebeveyn tarafından görünüm eklemek istediğimde olur

View root = inflater.inflate(R.layout.single, null);
LinearLayout lyt = root.findViewById(R.id.lytRoot);
lytAll.addView(lyt);  // ->  crash

böyle bir üst görünüm eklemelisiniz

View root = inflater.inflate(R.layout.single, null);
LinearLayout lyt = root.findViewById(R.id.lytRoot);
lytAll.addView(root);

2

Önce alt görünümü üst öğesinden kaldırmalısınız.

Projeniz Kotlin'deyse, çözümünüz Java'dan biraz farklı görünecektir. Kotlin as?, sol tarafı null veya döküm başarısız olursa null döndürerek döküm işlemini basitleştirir .

(childView.parent as? ViewGroup)?.removeView(childView)
newParent.addView(childView)

Kotlin Uzatma Çözümü

Bunu bir kereden fazla yapmanız gerekiyorsa, kodunuzu daha okunabilir hale getirmek için bu uzantıyı ekleyin.

childView.removeSelf()

fun View?.removeSelf() {
    this ?: return
    val parentView = parent as? ViewGroup ?: return
    parentView.removeView(this)
}

Bu Görünüm null, üst görünüm null veya üst görünüm bir ViewGroup değilse güvenli bir şekilde hiçbir şey yapmaz


1

Başka bir düzeltme buldum:

if (mView.getParent() == null) {
                    myDialog = new Dialog(MainActivity.this);
                    myDialog.setContentView(mView);
                    createAlgorithmDialog();
                } else {
                    createAlgorithmDialog();
                }

Burada sadece görünüm bir üst olup olmadığını kontrol if ifadesi var ve yeni iletişim kutusu oluşturmadıysanız, contentView ayarlamak ve benim "createAlgorithmDialog ()" yönteminde iletişim kutusunu göstermek.

Bu ayrıca onClickListeners ile pozitif ve negatif düğmeleri (ok ve iptal düğmeleri) ayarlar.


0

Bir görünümün çocuk olup olmadığını kontrol etmek için bu yöntemi kullanabilirsiniz.

public static boolean hasChildren(ViewGroup viewGroup) {
    return viewGroup.getChildCount() > 0;
 }

0

Benim durumum zaten farklı bir üst görünüm vardı çocuk görünümü farklıydı ben üst görünüm içinde çocuk görünümü farklı üst için ekliyorum. aşağıdaki örnek kod

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/lineGap"
>
<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="@color/black1"
    android:layout_gravity="center"
    android:gravity="center"
    />

</LinearLayout>

Ve bu görünümü şişiriyor ve başka bir LinearLayout'a ekliyordum, sonra LinaarLayout'u yukarıdaki düzenden kaldırdım ve çalışmaya başladı

Aşağıdaki kod sorunu çözdü:

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:gravity="center"
   android:textColor="@color/black1" />

0

Benim sorunum diğer cevapların birçoğu ile ilgili, ama değişikliği yapmak için biraz farklı bir neden ... Bir etkinliği bir parçaya dönüştürmeye çalışıyordum. Bu yüzden şişirme kodunu onCreate'den onCreateView'a taşıdım, ancak setContentView'den şişirme yöntemine dönüştürmeyi unuttum ve aynı IllegalStateException beni bu sayfaya getirdi.

Bunu değiştirdim:

binding = DataBindingUtil.setContentView(requireActivity(), R.layout.my_fragment)

buna:

binding = DataBindingUtil.inflate(inflater, R.layout.my_fragment, container, false)

Bu sorunu çözdü.

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.