Search code examples
androidandroid-viewpagerandroid-viewandroid-scrollview

How to get view height considering its parent has infinite height?


I have ScrollView that contains two ViewPagers. Top pager's height is always 48dp. I want bottom pager's height to be equal to current page height. So I thought I will programatically change ViewPager's height to current page height on every page change event. However, when I call getHeight() on my current page view it returns height of visible area of the view. Instead I want to get height of a view considering its parent has infinite height, i.e., like the view was put to ScrollView and not in ViewPager. Is it possible to measure this?

XML:

<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <android.support.v4.view.ViewPager
            android:id="@+id/top_pager"
            android:layout_width="match_parent"
            android:layout_height="48dp" >
        </android.support.v4.view.ViewPager>

        <android.support.v4.view.ViewPager
            android:id="@+id/bottom_pager"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </android.support.v4.view.ViewPager>
    </LinearLayout>
</ScrollView>

JAVA:

bottomPager.setOnPageChangeListener(new OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {
            Object pageTag = bottomPager.getTag();
            View currentPageView = bottomPager.findViewWithTag(pageTag);

            int height = currentPageView.getHeight();
            // height above is always smaller than the screen height
            // no matter how much content currentPage has.
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageScrollStateChanged(int state) {
        }
    });

Solution

  • Thanks Hugo Gresse. I ended up writing this class and I'm happy with the result.

    /**
     * This ViewPager continuously adjusts its height to the height of the current
     * page. This class works assuming that each page view has tag that is equal to
     * page position in the adapter. Hence, make sure to set page tags when using
     * this class.
     */
    public class HeightAdjustingViewPager extends ViewPager {
    
        public HeightAdjustingViewPager(Context context) {
            super(context);
        }
    
        public HeightAdjustingViewPager(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            for (int i = 0; i < getChildCount(); i++) {
                View pageView = getChildAt(i);
                pageView.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
                int pageHeight = pageView.getMeasuredHeight();
    
                Object pageTag = pageView.getTag();
                if (pageTag.equals(getCurrentItem())) {
                    heightMeasureSpec = MeasureSpec.makeMeasureSpec(pageHeight, MeasureSpec.EXACTLY);
                }
            }
    
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
    }