I have a custom ViewGroup that has a child ViewPager
. The ViewPager is fed by a PagerAdapter
that provides a LinearLayout
to the ViewPager
which has LayoutParams
of WRAP_CONTENT
on both height and width.
The view displays correctly but when the child.measure()
method is called on the ViewPager it does not return the actual dimensions of the LinearLayout but seems to fill all the remaining space.
Any ideas why this is happening and how to amend it?
You can create swipe views using AndroidX's ViewPager widget. To use ViewPager and tabs, you need to add a dependency on ViewPager and on Material Components to your project. To insert child views that represent each page, you need to hook this layout to a PagerAdapter .
This function is deprecated.
No. It is already set to the minimum possible value: one page to each side of the viewed page. This is necessary to have the animation effects work -- you see parts of two fragments (original and new) at the same time.
ViewPager in Android allows the user to flip left and right through pages of data. In our android ViewPager application we'll implement a ViewPager that swipes through three views with different images and texts.
I wasn't very happy with the accepted answer (nor with the pre-inflate-all-views solution in the comments), so I put together a ViewPager
that takes its height from the first available child. It does this by doing a second measurement pass, allowing you to steal the first child's height.
A better solution would be to make a new class inside the android.support.v4.view
package that implements a better version of onMeasure
(with access to package-visible methods like populate()
)
For the time being, though, the solution below suits me fine.
public class HeightWrappingViewPager extends ViewPager {
public HeightWrappingViewPager(Context context) {
super(context);
}
public HeightWrappingViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec)
== MeasureSpec.AT_MOST;
if(wrapHeight) {
/**
* The first super.onMeasure call made the pager take up all the
* available height. Since we really wanted to wrap it, we need
* to remeasure it. Luckily, after that call the first child is
* now available. So, we take the height from it.
*/
int width = getMeasuredWidth(), height = getMeasuredHeight();
// Use the previously measured width but simplify the calculations
widthMeasureSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
/* If the pager actually has any children, take the first child's
* height and call that our own */
if(getChildCount() > 0) {
View firstChild = getChildAt(0);
/* The child was previously measured with exactly the full height.
* Allow it to wrap this time around. */
firstChild.measure(widthMeasureSpec,
MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
height = firstChild.getMeasuredHeight();
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
}
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