Anak yang ditentukan sudah memiliki orangtua. Anda harus memanggil removeView () pada orang tua anak terlebih dahulu (Android)


164

Saya harus sering beralih di antara dua tata letak. Kesalahan terjadi pada tata letak yang diposting di bawah ini.

Ketika tata letak saya disebut pertama kali, tidak ada kesalahan dan semuanya baik-baik saja. Ketika saya kemudian memanggil tata letak yang berbeda (yang kosong) dan kemudian memanggil tata letak saya untuk kedua kalinya, itu melempar kesalahan berikut:

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

Lay-code saya terlihat seperti ini:

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

Saya tahu pertanyaan ini telah diajukan sebelumnya, tetapi itu tidak membantu dalam kasus saya.


1
Hanya untuk seseorang yang mendapat kesalahan yang sama: Pastikan Anda menambahkan elemen yang benar. Katakanlah Anda harus menambahkan LinearLayouttetapi Anda menambahkan TextView. Jadi perbaiki.
Pengembang

saat menggunakan penyatuan data android seharusnya tidak menyatakan tampilan dengan id 'root', itu menyebabkan kesalahan yang sama.
Mohammad Reza Khahani

bagi yang menggunakan TranstitionManager.beginDelayedTransition, silakan periksa jawaban
mochadwi

Jawaban:


354

Pesan kesalahan mengatakan apa yang harus Anda lakukan.

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

56

cukup berikan argumen attachtoroot sebagai false

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

2
Bagi saya, ini adalah bullseye. Batasi tata letak untuk item dalam recycleView, yang secara dinamis mengubah batasan berdasarkan runtime. ConstraintSet.apply tidak berfungsi, sampai ini. Jadi, sebarkan induk di onCreateViewHolder, tetapi kirim false sebagai parameter tambahan untuk digembungkan.
miroslavign

3
Ini solusi yang tepat! Seperti yang dikatakan @Sniper, meneruskan null ke param kedua dapat menyebabkan tampilan anak tidak menyelaraskan dirinya sebagaimana seharusnya ke induknya. OTOH melewati orang tua dapat menyebabkan kesalahan yang dimaksud. Jadi, attachToRoot= salah, adalah jalan yang harus ditempuh.
Vassilis

Cara yang benar untuk melakukannya.
Rowland Mtetezi

50

Saya datang ke sini untuk mencari kesalahan dengan recyclerview saya tetapi solusinya tidak bekerja (jelas). Saya telah menulis penyebab dan solusi untuknya dalam kasus recyclerview. Semoga ini bisa membantu seseorang.

Kesalahan ini disebabkan jika dalam onCreateViewHolder()metode berikut ini diikuti:

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

Sebaliknya seharusnya

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

15
Terkadang jawaban acak yang bukan jawaban untuk pertanyaan yang diajukan membantu orang lain. Ini berhasil untuk saya. Terima kasih!
Ajith Memana

1
Bagus !, dan itulah mengapa orang-orang harus melewati "null" sebagai parameter 2d di inflaters. Terima kasih.
super Pengguna

4
Melewati Null ke parameter yang bertanggung jawab untuk orang tua bukanlah ide yang buruk, tetapi Anda harus tahu bahwa dalam kasus ini tampilan anak (yang Anda kembang) tidak akan dapat mengukurnya sendiri dengan benar dalam beberapa kasus, karena tidak tahu apa-apa tentang orang tua. Dalam beberapa kasus itu akan berhasil tetapi dalam beberapa tidak.
Stoycho Andreev

1
Perhatikan bahwa ini dapat menyebabkan tema pemirsa tidak terselesaikan dengan benar.
SpaceBison

13

Saya mendapat pesan ini saat mencoba melakukan fragmen menggunakan attach to root to true, bukan false, seperti:

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

Setelah melakukan:

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

Itu berhasil.


5

Jika solusi lain tidak berfungsi seperti:

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

periksa apa yang Anda kembali dari onCreateView dari fragmen apakah itu tampilan tunggal atau grup tampilan? dalam kasus saya, saya punya viewpager pada root xml of fragment dan saya kembali viewpager, ketika saya menambahkan viewgroup dalam tata letak saya tidak memperbarui bahwa saya harus mengembalikan viewgroup sekarang, bukan viewpager (tampilan).


5

frameLayout.addView (bannerAdView); <----- jika Anda mendapatkan kesalahan pada baris ini, lakukan seperti di bawah ini ..

if (bannerAdView.getParent() != null)

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

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

4

Kesalahan saya adalah mendefinisikan tampilan seperti ini:

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

Itu hilang:

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

3

Dalam kasus saya masalahnya disebabkan oleh fakta bahwa saya menggembungkan tampilan induk dengan <merge>tata letak. Dalam hal ini, addView()menyebabkan crash.

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

Menghapus addView()membantu memecahkan masalah.


2

periksa apakah Anda sudah menambahkan tampilan

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

2

Kode di bawah ini menyelesaikannya untuk saya:

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

Catatan: Kesalahan berasal dari kelas fragmen saya dan dengan mengganti metode onDestroy seperti ini, saya bisa menyelesaikannya.



2

Dalam kasus saya itu terjadi ketika saya ingin menambahkan tampilan oleh orang tua ke tampilan lain

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

Anda harus menambahkan tampilan induk seperti ini

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

2

Anda harus terlebih dahulu menghapus tampilan anak dari induknya.

Jika proyek Anda berada di Kotlin, solusi Anda akan terlihat sedikit berbeda dari Java. Kotlin menyederhanakan casting dengan as?, mengembalikan nol jika sisi kiri adalah nol atau pemain gagal.

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

Solusi Ekstensi Kotlin

Jika Anda perlu melakukan ini lebih dari sekali, tambahkan ekstensi ini untuk membuat kode Anda lebih mudah dibaca.

childView.removeSelf()

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

Dengan aman tidak akan melakukan apa pun jika Tampilan ini adalah nol, tampilan induk adalah nol, atau tampilan induk bukan merupakan ViewGroup


1

Saya menemukan perbaikan lain:

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

Di sini saya hanya memiliki pernyataan if memeriksa apakah tampilan memiliki orangtua dan jika tidak membuat dialog baru, mengatur contentView dan menampilkan dialog dalam metode "createAlgorithmDialog ()" saya.

Ini juga mengatur tombol positif dan negatif (tombol ok dan batal) dengan onClickListeners.


0

Anda dapat menggunakan metode ini untuk memeriksa apakah suatu pandangan memiliki anak atau tidak.

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

0

Kasus saya berbeda tampilan anak sudah memiliki tampilan induk saya menambahkan tampilan anak di dalam tampilan induk ke induk yang berbeda. contoh kode di bawah ini

<?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>

Dan saya menggembungkan pandangan ini dan menambahkan ke LinearLayout lain, kemudian saya menghapus LinaarLayout dari tata letak di atas dan mulai bekerja

kode di bawah ini memperbaiki masalah:

<?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

Masalah saya terkait dengan banyak jawaban lain, tetapi alasan yang sedikit berbeda karena perlu melakukan perubahan ... Saya mencoba untuk mengubah suatu Kegiatan menjadi Fragmen. Jadi saya memindahkan kode mengembang dari onCreate ke onCreateView, tapi saya lupa untuk mengonversi dari setContentView ke metode mengembang, dan IllegalStateException yang sama membawa saya ke halaman ini.

Saya mengubah ini:

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

untuk ini:

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

Itu memecahkan masalah.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.