У вказаної дитини вже є батько. Ви повинні спочатку зателефонувати на RemoveView () батька дитини (Android)


164

Доводиться часто перемикатися між двома макетами. Помилка відбувається в макеті, розміщеному нижче.

Коли мій макет викликається вперше, не виникає помилок і все в порядку. Коли я називаю інший макет (порожній) і після цього називаю свій макет вдруге, він видає таку помилку:

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

Мій макет-код виглядає так:

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

Я знаю, що це питання було задано і раніше, але це не допомогло в моєму випадку.


1
Тільки для того, хто отримує таку ж помилку. Переконайтеся, що ви додали правильний елемент. Скажімо, ви повинні додавати, LinearLayoutале ви додаєте TextView. Тож виправте це.
розробник

при використанні Android-прив'язки даних не повинно оголошувати перегляд з id 'root', це може призвести до тієї ж помилки.
Мохаммед Реза Хахані

для тих, хто використовує TranstitionManager.beginDelayedTransition, будь ласка, перевірте мою відповідь тут
mochadwi

Відповіді:


354

Повідомлення про помилку говорить про те, що ви повинні зробити.

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

56

просто передайте аргумент attachtoroot як хибний

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

2
Для мене це було бичаче око. Макет обмежень для елементів у recycleView, що динамічно змінюються обмеженнями на основі часу виконання. До цього не працював ConstraintSet.apply. Отже, розповсюджуйте батьківську програму в onCreateViewHolder, але надсилайте false як додатковий параметр надуваючого.
miroslavign

3
Це правильне рішення! Як сказав @Sniper, передача нуля до другої парами може призвести до того, що подання дитини не вирівняється як слід до свого батька. OTOH, що передає батьків, може спричинити помилку. Отже, attachToRoot= false, це шлях.
Василіс

Правильний спосіб це зробити.
Rowland Mtetezi

50

Я прийшов сюди, щоб пошукати помилку з моїм рециркулятором, але рішення не працювало (очевидно). Я написав причину та рішення для неї у випадку перегляду рециркулятора. Сподіваюся, це комусь допоможе.

Помилка викликається, якщо onCreateViewHolder()дотримуватися наступного методу:

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

Натомість так і має бути

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

15
Іноді випадкові відповіді, які не є точно відповідями на поставлені запитання, допомагають комусь іншому. Це працювало для мене. Дякую!
Аджит Мемана

1
Приємно !, і саме тому люди в основному повинні передавати "null" як 2d параметри надувних. Дякую.
superUser

4
Передавання Null параметру, відповідальному за батьківського, не є поганою ідеєю, але ви повинні знати, що в такому випадку дитячий погляд (той, який ви надули) не зможе правильно вимірювати його в деяких випадках, тому що це не нічого не знаю про батьків. У деяких випадках це спрацює, але в деяких - ні.
Стойчо Андрєєв

1
Зауважте, що це може призвести до неправильного вирішення теми для глядачів.
SpaceBison

13

Я отримав це повідомлення під час спроби зробити фрагмент, використовуючи приєднати корінь до істини замість хибного, наприклад:

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

Після виконання:

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

Це спрацювало.


5

Якщо інше рішення не працює, як:

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

перевірте, для чого ви повертаєтеся з фрагмента onCreateView - це одиночний вигляд чи група перегляду? у моєму випадку у мене був viewpager на корені xml фрагмента, і я повертав viewpager, коли я додав viewgroup у макет, я не оновлював, що мені потрібно повернути viewgroup зараз, а не viewpager (view).


5

frameLayout.addView (банерAdView); <----- якщо ви отримаєте помилку в цьому рядку, зробіть, як показано нижче ..

if (bannerAdView.getParent() != null)

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

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

4

Моєю помилкою було визначити перегляд таким:

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

Він відсутній:

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

3

У моєму випадку проблема була викликана тим, що я надував батьківський вигляд <merge>макетом. У цьому випадку addView()спричинили збій.

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

Видалення addView()допомогло вирішити проблему.



2

Код нижче вирішив це для мене:

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

Примітка. Помилка була з мого класу фрагментів, і, замінивши такий метод onDestroy, я міг її вирішити.



2

У моєму випадку це трапляється, коли я хочу додати перегляд батьком до іншого подання

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

ви повинні додати батьківський вигляд таким

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

2

Спочатку потрібно видалити подання дитини від його батьків.

Якщо ваш проект знаходиться в Котліні, ваше рішення буде виглядати трохи інакше, ніж Java. Котлін спрощує додавання as?, повертаючи нульове значення, якщо ліва сторона є нульовою або відмінена.

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

Рішення розширення Kotlin

Якщо вам потрібно зробити це не один раз, додайте це розширення, щоб зробити ваш код більш читабельним.

childView.removeSelf()

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

Він безпечно нічого не зробить, якщо цей перегляд є нульовим, батьківський вигляд - нульовим або батьківський подання не є ViewGroup


1

Я знайшов ще одне виправлення:

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

Тут я просто перевіряю, якщо у заяві перевіряється, чи був у представника батько, і якщо він не створив нове діалогове вікно, встановіть contentView і покажіть діалогове вікно в моєму методі "createAlgorithmDialog ()".

Це також встановлює позитивні та негативні кнопки (кнопки "ОК" та "Скасувати") onClickListeners.


0

Ви можете скористатися цим методом, щоб перевірити, чи є у представників дітей чи ні.

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

0

У моєму випадку було інше, подання дитини вже було поданням батьків, я додаю подання дитини всередині батьківського подання до іншого батька. Приклад коду нижче

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

І я надував цей погляд і додав до іншого LinearLayout, тоді я видалив LinaarLayout з вищевказаного макета і його почала працювати

нижче коду виправлено проблему:

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

Моя проблема пов'язана з багатьма іншими відповідями, але трохи іншою причиною необхідності внесення змін ... Я намагався перетворити активність у фрагмент. Тому я перемістив надувний код з onCreate в onCreateView, але я забув перетворити з setContentView в метод надуття, і той самий IllegalStateException привів мене на цю сторінку.

Я змінив це:

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

до цього:

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

Це вирішило проблему.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.