Skip to content

Instantly share code, notes, and snippets.

@mrleolink
Last active February 8, 2018 03:17
Show Gist options
  • Save mrleolink/83968489070437a059f6a005307549cd to your computer and use it in GitHub Desktop.
Save mrleolink/83968489070437a059f6a005307549cd to your computer and use it in GitHub Desktop.
ViewPager that wraps current page's height
import android.content.Context;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
/**
* {@link ViewPager} that wraps current page's height
*
* @author Leo
*/
public class WrapContentViewPager extends ViewPager {
private Adapter mAdapter;
public WrapContentViewPager(Context context) {
this(context, null);
}
public WrapContentViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public void setAdapter(PagerAdapter adapter) {
if (!(adapter instanceof Adapter))
throw new IllegalArgumentException("Adapter of WrapContentViewPager has to implement WrapContentViewPager.Adapter");
mAdapter = (Adapter) adapter;
super.setAdapter(adapter);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
View child = mAdapter == null ? null : mAdapter.getCurrentPageView(getCurrentItem());
if (child != null) {
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height) height = h;
} else if (getAdapter() != null && getAdapter().getCount() > 0) {
post(this::requestLayout); // recur until we can get reference to the current page view
}
if (height != 0) {
height += getPaddingTop() + getPaddingBottom(); // take padding into account
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
public interface Adapter {
/**
* <p>Get view for currently selected page of the ViewPager.
* <p>Since this method is only called to get the View of current page, so implementation of this method should
* NOT keep references to ALL pages of the ViewPager, but utilize
* {@link PagerAdapter#destroyItem(ViewGroup, int, Object)} to remove unnecessary references instead.
* <p>Or you can override {@link PagerAdapter#setPrimaryItem(ViewGroup, int, Object)} to grab reference to
* current view.
*
* @param currentPosition current page of the ViewPager
* @return {@link View} instance of the current page
*/
@Nullable
View getCurrentPageView(int currentPosition);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment