지정된 자식에 이미 부모가 있습니다. 먼저 자녀의 부모에서 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. 그래서 고치세요.
개발자

안드로이드 데이터 바인딩을 사용할 때 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 인수를 false로 전달하십시오.

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

2
나에게 이것은 불즈 아이였습니다. recycleView의 항목에 대한 제약 조건 레이아웃으로 런타임에 따라 제약 조건이 동적으로 변경됩니다. 이 때까지 ConstraintSet.apply가 작동하지 않았습니다. 따라서 onCreateViewHolder에서 부모를 전파하지만 팽창에 추가 매개 변수로 false를 보냅니다.
miroslavign

3
이것이 올바른 해결책입니다! @Sniper가 말했듯이 두 번째 매개 변수에 null을 전달하면 자식보기가 부모에 맞게 자체적으로 정렬되지 않을 수 있습니다. 부모를 전달하는 OTOH는 해당 오류를 일으킬 수 있습니다. 따라서 attachToRoot= 거짓은 갈 길입니다.
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

1
Nice !, 그래서 사람들은 대부분 팽창기에서 2 차원 매개 변수로 "널"을 전달해야합니다. 감사.
수퍼 유저

4
부모를 담당하는 매개 변수에 Null을 전달하는 것은 나쁜 생각이 아니지만이 경우 자식 뷰 (부풀린 뷰)는 그렇지 않은 경우 자체 뷰를 올바르게 측정 할 수 없다는 것을 알아야합니다. 부모에 대해 아는 것 어떤 경우에는 효과가 있지만 어떤 경우에는 효과가 없습니다.
Stoycho Andreev

1
이로 인해 조회자 테마가 올바르게 해결되지 않을 수 있습니다.
SpaceBison

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가 있었고 레이아웃에 viewgroup을 추가 할 때 viewpager (view)가 아닌 viewgroup을 반환해야한다고 업데이트하지 않았습니다.


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

아래 코드는 나를 위해 해결했습니다.

@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)

코 틀린 확장 솔루션

이 작업을 두 번 이상 수행해야하는 경우 코드를 더 읽기 쉽게하려면이 확장을 추가하십시오.

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

여기에 뷰에 부모가 있는지 확인하고 새 대화 상자를 만들지 않은 경우 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)

문제가 해결되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.