Search code examples
androidviewviewgroup

removeView not working after LayoutInflater.inflate(resource, root, true)


I add and remove a view dynamically to a custom view (FrameLayout) doing this:

LayoutInflater inflater = (LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mMyView = inflater.inflate(resId, this, true);

Later on I try to remove the view but the view won't remove:

removeView(mMyView);

If I do this instead everything works as expected:

mMyView = inflater.inflate(resId, this, **false**);
addView(mMyView);

The only difference is that I manually add the view instead of letting the inflate call do it. Does anyone know why this would make a difference?


Solution

  • The answer lies in this call

    mMyView = inflater.inflate(resId, this, true);
    

    The documentation states:

    Returns The root View of the inflated hierarchy. If root was supplied and attachToRoot is true, this is root; otherwise it is the root of the inflated XML file.

    http://developer.android.com/reference/android/view/LayoutInflater.html#inflate(int, android.view.ViewGroup, boolean)

    I was assuming the inflate call always returns the root of the inflated layout (defined by resId) but if the root parameter is provided and attachToRoot is true then it's the root of the layout the inflated layout was added to (it's new parent view) and that's root (in this case root == this).

    So while

    mMyView = inflater.inflate(resId, this, false);
    

    assigns the view to mMyView that we want to remove later

    mMyView = inflater.inflate(resId, this, true);
    

    assigns the parent of that view. The call removeView(mMyView) is actually identical to removeView(this) and that obviously doesn't do anything.

    This behavior is IMO very counter-intuitive and prone to errors. Why should it return the root layout instead of the inflated layout when we already have that root layout with the root parameter while we don't have a reference to the inflated layout yet?