[android] Android: I am unable to have ViewPager WRAP_CONTENT

I also ran into this problem, but in my case I had a FragmentPagerAdapter that was supplying the ViewPager with its pages. The problem I had was that onMeasure() of the ViewPager was called before any of the Fragments had been created (and therefore could not size itself correctly).

After a bit of trial and error, I found that the finishUpdate() method of the FragmentPagerAdapter is called after the Fragments have been initialized (from instantiateItem() in the FragmentPagerAdapter), and also after/during the page scrolling. I made a small interface:

public interface AdapterFinishUpdateCallbacks
{
    void onFinishUpdate();
}

which I pass into my FragmentPagerAdapter and call:

@Override
public void finishUpdate(ViewGroup container)
{
    super.finishUpdate(container);

    if (this.listener != null)
    {
        this.listener.onFinishUpdate();
    }
}

which in turn allows me to call setVariableHeight() on my CustomViewPager implementation:

public void setVariableHeight()
{
    // super.measure() calls finishUpdate() in adapter, so need this to stop infinite loop
    if (!this.isSettingHeight)
    {
        this.isSettingHeight = true;

        int maxChildHeight = 0;
        int widthMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY);
        for (int i = 0; i < getChildCount(); i++)
        {
            View child = getChildAt(i);
            child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, MeasureSpec.UNSPECIFIED));
            maxChildHeight = child.getMeasuredHeight() > maxChildHeight ? child.getMeasuredHeight() : maxChildHeight;
        }

        int height = maxChildHeight + getPaddingTop() + getPaddingBottom();
        int heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);

        super.measure(widthMeasureSpec, heightMeasureSpec);
        requestLayout();

        this.isSettingHeight = false;
    }
}

I am not sure it is the best approach, would love comments if you think it is good/bad/evil, but it seems to be working pretty well in my implementation :)

Hope this helps someone out there!

EDIT: I forgot to add a requestLayout() after calling super.measure() (otherwise it doesn't redraw the view).

I also forgot to add the parent's padding to the final height.

I also dropped keeping the original width/height MeasureSpecs in favor of creating a new one as required. Have updated the code accordingly.

Another problem I had was that it wouldn't size itself correctly in a ScrollView and found the culprit was measuring the child with MeasureSpec.EXACTLY instead of MeasureSpec.UNSPECIFIED. Updated to reflect this.

These changes have all been added to the code. You can check the history to see the old (incorrect) versions if you want.