Originally I got this error:
The specified child already has a parent. You must call removeView() on the child's parent first
at
customSection.addView(customLayout);
So I added
((LinearLayout)customLayout.getParent()).removeView(customLayout);
and now get
java.lang.NullPointerException
So if the child has a parent, and I must first remove the child from the parent, why does getParent() return null?
I have an abstract fragment that allows derived classes to supply a custom layout for the list adapter. Relevant code:
Binding:
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;
}
I've also tried inflater.inflate(R.layout.list_item_custom_section, null) ... false, null / false, what gives?
EDIT:
@allprog, I knew some cleanup was needed. I wrote this at the end of the day somewhat in a hurry. I have since cleaned up the code, and separated out the binding and inflating of the view. Cleaned up code:
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);
        }
}
Child class:
    @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));
    }
suitianshi got it first, with my original [unkempt] code that was the solution.
try this:
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);
    }
}
I have read related source code, getParent should return non-null value when view has a parent. You should make sure it actually has a parent before casting and calling removeView
Wish this helps.
source code :
in View :
public final ViewParent getParent() {
        return mParent;
    }
in 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.");
}
As I can see your parentView is a field variable, this is the key. So what I suspect is really going on:
First call of bind(): you creating parentView and it is not have a parent yet, customSection.addView(customLayout); works fine, but after you added a check for parent it fails here.
Second call of bind(): parentView is now have a parent and your added check should work now, but you failed at the previous step. Without a check you are failing here with exception in title.
Solution: check for the presence of parent and remove it only if necessery.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With