指定的子项已有父项.你必须首先在孩子的父母上调用removeView()(Android)

bla*_*0ne 137 java android parent-child textview android-edittext

在我的应用程序中,我必须经常在两个布局之间切换.错误发生在下面发布的布局中.

第一次调用我的布局时,没有发生任何错误,一切都很好.当我再调用一个不同的布局(一个空白的布局),然后再次调用我的布局时,它会给我以下错误:

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

我的布局代码如下所示:

    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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道之前已经问过这个问题,但在我的案例中没有帮助.

Zie*_*ony 307

错误消息说明您应该做什么.

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


suk*_*uku 46

我来到这里是用我的recyclerview搜索错误,但解决方案不起作用(显然).在Recyclerview的情况下,我已经为它写了原因和解决方案.希望它可以帮助某人.

如果onCreateViewHolder()遵循以下方法,则会导致错误:

layoutInflater = LayoutInflater.from(context);
return new VH(layoutInflater.inflate(R.layout.single_row, parent));
Run Code Online (Sandbox Code Playgroud)

相反它应该是

return new VH(layoutInflater.inflate(R.layout.single_row, null));
Run Code Online (Sandbox Code Playgroud)

  • 有时随机答案不完全是问题的答案,可以帮助其他人.这对我有用.谢谢! (12认同)
  • 将Null传递给负责父项的参数并不是一个坏主意,但你必须知道,在这种情况下,子视图(你膨胀的那个)在某些情况下无法正确测量它,因为它没有了解父母的一切.在某些情况下,它会起作用但在某些情况下不会. (4认同)

Pb *_*ies 42

只需将attachtoroot参数传递为false即可

View view = inflater.inflate(R.layout.child_layout_to_merge, parent_layout, false);
Run Code Online (Sandbox Code Playgroud)

  • 这是正确的解决方案!正如@Sniper 所说,将 null 传递给第二个参数会导致子视图不会像它应该的那样与其父视图对齐。OTOH 通过父级可能会导致有问题的错误。所以,`attachToRoot` = false,是要走的路。 (3认同)
  • 对我来说,这是一个靶心。recycleView 中项目的约束布局,基于运行时动态更改约束。ConstraintSet.apply 没有工作,直到这个。因此,在 onCreateViewHolder 中传播父级,但将 false 作为附加参数发送到膨胀。 (2认同)

Gib*_*olt 16

您必须首先从其父视图中删除子视图。

如果您的项目使用 Kotlin,您的解决方案看起来将与 Java 略有不同。Kotlin 使用 简化了转换as?,如果左侧为 null 或转换失败,则返回 null。

(childView.parent as? ViewGroup)?.removeView(childView)
newParent.addView(childView)
Run Code Online (Sandbox Code Playgroud)

Kotlin 扩展解决方案

如果您需要多次执行此操作,请添加此扩展以使您的代码更具可读性。

childView.removeSelf()

fun View?.removeSelf() {
    this ?: return
    val parentView = parent as? ViewGroup ?: return
    parentView.removeView(this)
}
Run Code Online (Sandbox Code Playgroud)

如果此 View 为 null、父视图为 null 或父视图不是 ViewGroup,它将安全地不执行任何操作


Hud*_*ira 12

我尝试使用attach to root to true而不是false来提交此消息,如下所示:

return inflater.inflate(R.layout.fragment_profile, container, true)
Run Code Online (Sandbox Code Playgroud)

做完之后:

return inflater.inflate(R.layout.fragment_profile, container, false)
Run Code Online (Sandbox Code Playgroud)

有效.


May*_*bhi 8

frameLayout.addView(bannerAdView); <----- 如果您在这一行遇到错误,请执行以下操作..

if (bannerAdView.getParent() != null)

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

   frameLayout.addView(bannerAdView);     <------ now added view
Run Code Online (Sandbox Code Playgroud)


Hit*_*ahu 8

在 KOTLIN 中简化

 viewToRemove?.apply {
            if (parent != null) {
                (parent as ViewGroup).removeView(this)
            }
        }
Run Code Online (Sandbox Code Playgroud)


Ric*_*bal 6

如果您使用 ViewBinding,请确保您引用的是正确的绑定!

当我尝试从活动中膨胀自定义对话框时,我遇到了这个问题:

AlertDialog.Builder builder = new AlertDialog.Builder(this);

final AlertBinding alertBinding = AlertBinding.inflate(LayoutInflater.from(this), null, false);

builder.setView(binding.getRoot()); // <--- I was using binding (which is my Activity's binding), instead of alertBinding.
Run Code Online (Sandbox Code Playgroud)


bla*_*awk 5

如果其他解决方案不起作用,例如:

View view = inflater.inflate(R.layout.child_layout_to_merge, parent_layout, false);
Run Code Online (Sandbox Code Playgroud)

检查您从片段的 onCreateView 返回的内容是单个视图还是视图组?在我的情况下,我在片段 xml 的根目录上有 viewpager,我正在返回 viewpager,当我在布局中添加 viewgroup 时,我没有更新我现在必须返回 viewgroup,而不是 viewpager(view)。


Ped*_*ina 5

我的错误是这样定义视图:

view = inflater.inflate(R.layout.qr_fragment, container);
Run Code Online (Sandbox Code Playgroud)

它不见了:

view = inflater.inflate(R.layout.qr_fragment, container, false);
Run Code Online (Sandbox Code Playgroud)


May*_*m R 5

就我而言,当我想将父视图添加到其他视图时,就会发生这种情况

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

你必须像这样添加父视图

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