Android动态表格布局 - 添加视图抛出异常IllegalStateException(子节点已经有父节点)

时间:2010-11-11 16:47:40

标签: android android-layout android-view

在Java中创建布局,因为所需的TableLayouts数量不称为设计时间。

当我致电IllegalStateException

时,我收到View告诉我将createPlayerTables()(从当前的父级)中移除,然后再将其分配给另一位家长

当我尝试将ImageView的List中的ImageView添加到第一个TableRow时,在此循环的第一行抛出异常:

for (int i = 0; i < 3; i++) {
    tableRowsLst.get(0).addView((ImageView) imageViewsLst.get(i));
    tableRowsLst.get(1).addView((ImageView) imageViewsLst.get(i+3));
}

错误表明ImageView已经已经添加到ViewGroup ,但是看到下面的代码,我创建了新的ImageViews,我只将它们添加到ViewGroup中它出错的行。 ,所以我不确定为什么会失败。

// List<ImageView> imageViewsLst = new ...
// List<TableRow> tableRowsLst = new ...

/**
* Initialises the TableLayouts, one per player
*/ 
private TableLayout createPlayerTables(int playerNum) {
    ...

    for (int i = 0; i < 6; i++) {
        imageViewsLst.add(new ImageView(this));
        ...
    }

    for (int i = 0; i < 3; i++) {
        tableRowsLst.add(new TableRow(this));
        ...
    }

    for (int i = 0; i < 3; i++) {
        tableRowsLst.get(0).addView((ImageView) imageViewsLst.get(i));
        tableRowsLst.get(1).addView((ImageView) imageViewsLst.get(i+3));
    }

    ...
}

3 个答案:

答案 0 :(得分:4)

在这个循环中:

for (int i = 0; i < 3; i++){
   tableRowsLst.add(new TableRow(this));
   tableRowsLst.get(i).setLayoutParams(
       new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, dipToPixels(55)));
   tableRowsLst.get(i).setOrientation(LinearLayout.HORIZONTAL);
}

您只是不断向TableRows添加新tableRowsLst,但您始终只使用前三个元素。

在循环之前清除列表:

tableRowsLst.clear();

答案 1 :(得分:2)

虽然在此示例中不是这种情况,但此问题的另一个常见原因是未正确使用onCreateDialog()onPrepareDialog()onCreateDialog()仅被调用一次,此处完成的任何操作都将持续存在。如果要将动态内容添加到布局(Dialog),则可能需要使用onPrepareDialog(),这将在创建后但在每次显示之前发生。引用Android documentation

  

在显示对话框之前,Android还会调用onPrepareDialog(int,Dialog)上的可选回调方法。如果要在每次打开时更改对话框的任何属性,请定义此方法。每次打开对话框时都会调用此方法,而onCreateDialog(int)仅在第一次打开对话框时调用。如果未定义onPrepareDialog(),则对话框将保持与上次打开时相同。此方法还传递了对话框的ID,以及您在onCreateDialog()中创建的Dialog对象。

答案 2 :(得分:1)

啊哈!好吧,经过几次错误的开始,这就是问题所在。

imageViewsList是一个成员变量。每次调用createPlayerTables时都会添加6个视图,然后每次使用第一个6。第一次传球(球员0),没问题。第二次传球(球员1):热潮。

选项1)不要保存它们。给定的代码不需要它们,尽管这并不能涵盖所有基础。你可以将它们从表格行中挖出来并将它们压缩。

选项2)取消playerNum * 6对{view = {}的访问权限{== imageViewsList.size()首次调用时createPlayerTables()

友好的建议:您可以通过几种不同的方式找到问题:

  • 在每次调用TableRow.add()之前使用对象ID的Log.d()将显示在第二次传递中使用的相同对象ID,紧接着是您的异常。
  • 在Handy Dandy Debugger中逐步执行代码。是的,这是很多代码可以逐步找出在这种情况下发生的事情。一些不同的断点可以更容易地看到对createPlayerTables()的哪个调用正在抛出,并且只有当它要抛出时才允许你进入cpt()。

问你自己“我能做些什么来抓住这个”每次你发现一个bug都会立即提高你的调试技能。