Android错误消息冲突:指定的子级已有父级.您必须首先在孩子的父母上调用removeView()

Jac*_*ack 6 android android-layout android-listview android-fragments

最初我收到了这个错误:

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

customSection.addView(customLayout);
Run Code Online (Sandbox Code Playgroud)

所以我补充道

((LinearLayout)customLayout.getParent()).removeView(customLayout);
Run Code Online (Sandbox Code Playgroud)

现在得到

java.lang.NullPointerException
Run Code Online (Sandbox Code Playgroud)

因此,如果孩子有父母,我必须先从父母那里删除孩子,为什么getParent()会返回null?

我有一个抽象的片段,允许派生类为列表适配器提供自定义布局.相关代码:

捆绑:

public void bind(DataObject row) {
    View customLayout = getChildItemView(row);
    if (customLayout != null) {
        ((LinearLayout) customLayout.getParent()).removeView(customLayout);
        customSection.removeAllViews();
        customSection.addView(customLayout);
        customSection.setVisibility(View.VISIBLE);
    } else {
        customLayout.setVisibility(View.INVISIBLE);
    }

}

protected View getChildItemView(CommonRow row) {
    if (parentView == null) {
        parentView = (LinearLayout) LayoutInflater.from(getActivity())
                .inflate(R.layout.list_item_custom_section,
                        new LinearLayout(getActivity()), true);
        label = (TextView) parentView.findViewById(R.id.txtData1Label);
        value = (TextView) parentView.findViewById(R.id.txtData1Value);
    }
    label.setText("Minimum");
    value.setText(manager.formatMoney(((SpecificDataRow) row).minimum));
    return parentView;
}
Run Code Online (Sandbox Code Playgroud)

我也试过inflater.inflate(R.layout.list_item_custom_section, null)......假,空/假,是什么给出的?

编辑:

@allprog,我知道需要一些清理工作.我在一天结束时写了这篇文章有点匆忙.我已经清理了代码,并分离出视图的绑定和膨胀.清理代码:

private class ViewHolder {
....

       public ViewHolder(View v) {
            Butterknife.inject(this, v);
            View custom = createCustomView(customSection);
            if (custom != null) {
                customSection.setVisibility(View.VISIBLE);
                customSection.addView(custom);
            }
        }

        public void bind(CommonRow row) {
            ......

            bindCustomView(row, customSection);
        }

}
Run Code Online (Sandbox Code Playgroud)

儿童班:

    @Override
    protected View createCustomView(ViewGroup parent) {
        return LayoutInflater.from(getActivity()).inflate(R.layout.list_item_custom_section, parent, false);
    }


    @Override
    protected void bindCustomView(CommonRow row, ViewGroup section) {
        TextView label = Views.findById(section, R.id.txtData1Label);
        TextView value = Views.findById(section, R.id.txtData1Value);

        label.setText("Minimum");
        value.setText(manager.formatMoney(((SpecificRow) row).minimum));
    }
Run Code Online (Sandbox Code Playgroud)

suitianshi首先得到它,我的原始[不整洁]代码是解决方案.

sui*_*shi 12

试试这个:

public void bind(DataObject row) {
    View customLayout = getChildItemView(row);
    if (customLayout != null) {
         if(customLayout.getParent() != null) {
             ((LinearLayout)customLayout.getParent()).removeView(customLayout);
         }

         customSection.removeAllViews();
         customSection.addView(customLayout);
         customSection.setVisibility(View.VISIBLE);
    } else {
         customLayout.setVisibility(View.INVISIBLE);
    }

}
Run Code Online (Sandbox Code Playgroud)

我已经阅读了相关的源代码,getParentview有父项时应该返回非空值.在投射和调用之前,你应该确保它实际上有一个父节点removeView

希望这有帮助.

源代码 :

View:

public final ViewParent getParent() {
        return mParent;
    }
Run Code Online (Sandbox Code Playgroud)

ViewGroup.addViewInner

if (child.getParent() != null) {
     throw new IllegalStateException("The specified child already has a parent. " +
         "You must call removeView() on the child's parent first.");
}
Run Code Online (Sandbox Code Playgroud)