How to wrap the height of a ViewPager to the height of its current Fragment?
Finally found a better solution for WrapContentViewPager!
The other solution contain some bug that hard to be solved, but I think this solution can be simply applied in our code
I found it on this site https://github.com/akhahaha/burn-android/blob/master/app/src/main/java/com/ucla/burn/android/WrapContentViewPager.java
Here is the code
public class WrapContentViewPager extends ViewPager {
public WrapContentViewPager(Context context) {
super(context);
}
public WrapContentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height) height = h;
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
I really liked @abhishek-v answer, but made some upgrades:
addPageChangeListener(...)
called inside ourViewPager
(don't need to callreMeasureCurrentPage(...)
manually outside on page swipe)- don't need to store
mCurrentPagePosition
, because we can usegetCurrentItem()
- removed waste
try/catch
block
ViewPager now looks like:
public class WrapContentViewPager extends ViewPager {
public WrapContentViewPager(Context context) {
super(context);
initPageChangeListener();
}
public WrapContentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
initPageChangeListener();
}
private void initPageChangeListener() {
addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
@Override
public void onPageSelected(int position) {
requestLayout();
}
});
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
View child = getChildAt(getCurrentItem());
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}
You can customize the ViewPager
to resize the ViewPager
to it's current page size on page swipe.
You can use the below code.
public class WrapContentViewPager extends ViewPager {
private int mCurrentPagePosition = 0;
public WrapContentViewPager(Context context) {
super(context);
}
public WrapContentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
try {
boolean wrapHeight = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST;
if (wrapHeight) {
View child = getChildAt(mCurrentPagePosition);
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
heightMeasureSpec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY);
}
}
} catch (Exception e) {
e.printStackTrace();
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public void reMeasureCurrentPage(int position) {
mCurrentPagePosition = position;
requestLayout();
}
}
Declare it in xml:
<your.package.name.WrapContentViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</your.package.name.WrapContentViewPager>
After that call reMeasureCurrentpage
function on page swipe.
final WrapContentViewPager wrapContentViewPager = (WrapContentViewPager) findViewById(R.id.view_pager);
wrapContentViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
wrapContentViewPager.reMeasureCurrentPage(wrapContentViewPager.getCurrentItem());
}
@Override
public void onPageScrollStateChanged(int state) {
}
});