简体   繁体   中英

ViewPager in ListView - Measure Height Dynamically (WRAP_CONTENT inflated in Adapter)

What I have going on is a ListView. That ListView uses an adapter to inflate a RelativeLayout that only contains one ViewPager.

in the getView for the adapter the custom PagerAdapter is instantiated for the ViewPager and .setAdapter is called for the ViewPager. RIGHT after setAdapter is called I do a return row or return view; That ends the getView method for that adapter in the ListView.

In the PagerAdapter I have implemented

public Object instantiateItem(View collection, int position) {}

This is basically what sets up the child views (pages) for the Pager Adapter. It does the inflating and setting all the children views and then adds the view to the collection.

I think the problem lies in the fact that after the return is done in the row, the PagerAdapter still hasnt finished setting up the children, so the ListView thinks the ViewPager is empty and draws it out to the screen that way. What I have done is what I think is a hack basically.

I try to measure the first child view in instantiateItem using something like this:

view.measure(MeasureSpec.makeMeasureSpec(widthMeasureSpecSize, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(heightMeasureSpecSize, MeasureSpec.UNSPECIFIED));
((Pager) collection).requestedHeight = view.getMeasuredHeight();

The values heightMeasureSpecSize actually is a public property that is set by the listView adapter before .setAdapter is called The ((Pager) collection).requestedHeight is another property I made on the ViewPager itself when I extended it. It defaults to 100 before a value is set to it. I then overrided the onMeasure method like so:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
    super.onMeasure(widthMeasureSpec, View.MeasureSpec.makeMeasureSpec(requestedHeight, View.MeasureSpec.AT_MOST));
}

With all this code, when I run the application, whenever onMeasure gets called on the ViewPager, the ListView seems to add the ViewPager to the list with 100 and then re-calculate using onMeasure and redraw the item using the measuredHeight of the first child of the View Pager....

All of this because wrap_content is broken in ViewPager. Is there a better way than doing this possibly? It seems terribly inefficient.

This is my solution:

    ViewTreeObserver viewTreeObserver = mViewPager.getViewTreeObserver();
    viewTreeObserver
            .addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

                @Override
                public void onGlobalLayout() {

                    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
                            LinearLayout.LayoutParams.WRAP_CONTENT,
                            LinearLayout.LayoutParams.WRAP_CONTENT);

                    int viewPagerWidth = mViewPager.getWidth();
                    float viewPagerHeight = (float) (viewPagerWidth * FEATURED_IMAGE_RATIO);

                    layoutParams.width = viewPagerWidth;
                    layoutParams.height = (int) viewPagerHeight;

                    mViewPager.setLayoutParams(layoutParams);
                    mViewPager.getViewTreeObserver()
                            .removeGlobalOnLayoutListener(this);
                }
            });

I measure and then adjust height. Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM