指定された子にはすでに親があります。最初に子の親でremoveView()を呼び出す必要があります(Android)


164

2つのレイアウトを頻繁に切り替える必要があります。下記のレイアウトでエラーが発生しています。

私のレイアウトが初めて呼び出されたとき、エラーは発生せず、すべて正常です。次に、別のレイアウト(空白のレイアウト)を呼び出し、その後、もう一度レイアウトを呼び出すと、次のエラーがスローされます。

> 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 databindingを使用すると、IDが 'root'のビューを宣言してはいけません。同じエラーが発生します。
Mohammad Reza Khahani

を使用している人は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引数をfalseとして渡すだけです

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

2
私にとって、これはブルズアイでした。recycleView内のアイテムの制約レイアウト。ランタイムに基づいて動的に制約を変更します。ConstraintSet.applyは、これまでは機能しませんでした。したがって、onCreateViewHolderで親を伝播しますが、追加のパラメーターとしてfalseをインフレートに送信します。
ミロスラヴィン2018年

3
これは正しい解決策です!@Sniperが言ったように、nullを2番目のパラメーターに渡すと、子ビューが親に合わせて整列されなくなる可能性があります。OTOHが親を渡すと、問題のエラーが発生する可能性があります。したがって、attachToRoot= falseは、進むべき道です。
Vassilis

それを行う正しい方法。
Rowland Mtetezi

50

私はrecyclerviewでエラーを検索するためにここに来ましたが、解決策は機能しませんでした(明らかに)。recyclerviewの場合の原因と解決策を書きました。それが誰かを助けることを願っています。

エラーは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
時々、質問に対する答えではないランダムな答えが誰かを助ける。これでうまくいきました。ありがとう!
Ajith Memana 2017

1
いいですね。それが、ほとんどの場合、インフレータの2Dパラメータとして「null」を渡す必要がある理由です。ありがとう。
superUser

4
親を担当するパラメーターにNullを渡すことは悪い考えではありませんが、この場合、子ビュー(展開するビュー)はそれを正しく測定できない場合があることを知っておく必要があります。親について何でも知っています。一部のケースでは機能しますが、一部のケースでは機能しません。
Stoycho Andreev

1
これにより、ビューホルダーのテーマが正しく解決されない場合があることに注意してください。
SpaceBison 2018年

13

次のように、ルートにアタッチしてfalseではなくtrueにフラグメントをコミットしようとしたときに、このメッセージが表示されました。

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から何が返されているかを確認してください。単一のビューですか、それともビューグループですか?私の場合、フラグメントのxmlのルートにviewpagerがあり、viewpagerを返していました。レイアウトにビューグループを追加したときに、viewpager(view)ではなく、ビューグループを返す必要があることを更新しませんでした。


5

frameLayout.addView(bannerAdView); <-----この行でエラーが発生した場合は、以下のようにします。

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

ビューがすでに追加されているかどうかを確認します

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

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

まず、親から子ビューを削除する必要があります。

プロジェクトがKotlinにある場合、ソリューションはJavaとは少し異なります。Kotlinはを使用してキャストを簡略化しas?、左側がnullであるかキャストが失敗した場合はnullを返します。

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

このビューがnull、親ビューがnull、または親ビューがViewGroupでない場合、安全に何もしません


1

別の修正を見つけました:

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

ここでは、ビューに親があるかどうかを確認するifステートメントがあり、それが新しいダイアログを作成しなかった場合は、contentViewを設定し、「createAlgorithmDialog()」メソッドでダイアログを表示します。

これにより、onClickListenersで正と負のボタン(OKボタンとキャンセルボタン)も設定されます。


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からinflateメソッドに変換するのを忘れたため、同じIllegalStateExceptionによってこのページが表示されました。

私はこれを変更しました:

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

これに:

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

それで問題は解決しました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.