I have to show a viewpager (An image and text below the image in pager row) inside a scrollview. I’m downloading the image, text from web and showing in pager rows. I wrapped viewpager inside a srollview to support the landscape mode too.
<com.xxx.myapp.android.ui.CustomScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:fadingEdge="none"
android:fillViewport="true"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="800dp"
android:layout_gravity="top"
android:layout_marginTop="10dp" />
</LinearLayout>
</com.xxx.myapp.android.ui.CustomScrollView>
And here is CustomScrollView. The problem is How can I set the view pager height based on its children height so that I can scroll the screen till the view pager item ends only. If I set view pager height to wrapcontent, nothing is showing in viewpager. If I set some 800dp then I can see the pager items but there is unnecessary scrolling in the screen. I dont want my scrollview to be scrolled beyond the pager childrens height. Please help me.
Wrap your pager row inside CustomScrollView instead of wrapping the pager inside CustomScrollview. And Don’t fix height of Viewpager as Piyush Gupath commented. Use wrapcontent.
Answer:
To fix the height of the viewpager we can customize the viewpager class.
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 {
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();
}
}
where this reMeasureCurrentPage should be called at viewpager onPageSelected callback.and CustomScrollView is the parent view.
Answer:
mViewPager = new ViewPager(mContext) {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
View view = getChildAt(this.getCurrentItem());
if (view != null) {
view.measure(widthMeasureSpec, heightMeasureSpec);
}
setMeasuredDimension(getMeasuredWidth(), measureHeight(heightMeasureSpec, view));
}
private int measureHeight(int measureSpec, View view) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
// set the height from the base view if available
if (view != null) {
result = view.getMeasuredHeight();
}
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(result, specSize);
}
}
return result;
}
};
Answer:
Try this way
<com.xxx.myapp.android.ui.CustomScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:fadingEdge="none"
android:fillViewport="true"
android:gravity="center">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:descendantFocusability="blocksDescendants"
android:orientation="vertical" >
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top"
android:layout_marginTop="10dp" />
</LinearLayout>
</com.xxx.myapp.android.ui.CustomScrollView>
Answer:
This is the best and easy solution :
1) Inside your custom ViewPager Class –
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
var heightMeasureSpec = heightMeasureSpec
val mode = MeasureSpec.getMode(heightMeasureSpec)
// Unspecified means that the ViewPager is in a ScrollView WRAP_CONTENT.
// At Most means that the ViewPager is not in a ScrollView WRAP_CONTENT.
if (mode == MeasureSpec.UNSPECIFIED || mode == MeasureSpec.AT_MOST) {
// super has to be called in the beginning so the child views can be initialized.
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
var height = 0
for (i in 0 until childCount) {
val child = getChildAt(i)
child.measure(
widthMeasureSpec,
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
)
val h = child.measuredHeight
if (h > height) height = h
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY)
}
// super has to be called again so the new specs are treated as exact measurements
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
2) While Setting the adapter to your ViewPager –
val viewPagerAdapter = ViewPagerAdapter(fragmentList, supportFragmentManager)
view_pager.adapter = viewPagerAdapter
view_pager.measure(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT)`
view_pager.currentItem = 0
Tags: androidandroid, scroll, view