I need to create an interface like Google Newsstand which is a sort of ViewPager (horizontal scroll) over a collapsing header (vertical scroll). One of my requirements is to
Add android:fillViewport="true"
in your NestedScrollView
. period.
I meet this problem ,i solve it by setFillViewport (true)
<android.support.v4.widget.NestedScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:id="@+id/nest_scrollview"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="mio.kon.yyb.nestedscrollviewbug.ScrollingActivity"
tools:showIn="@layout/activity_scrolling">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
in activity
NestedScrollView scrollView = (NestedScrollView) findViewById (R.id.nest_scrollview);
scrollView.setFillViewport (true);
I was having a similar problem (but without CollapsingToolbarLayout
, just a simple Toolbar
+ TabLayout
within the AppBarLayout
). I wanted the Toolbar to scroll out of sight when scrolling down the contents of a ViewPager
within the NestedScrollView
.
My layout went something like this:
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">
<android.support.v7.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"/>
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/my_tab_layout"
android:fillViewport="false"
app:tabMode="fixed"/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:layout_gravity="fill_vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v4.view.ViewPager
android:id="@+id/my_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v4.view.ViewPager>
</android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>
This layout wasn't working as intended, but I solved it by simply getting rid of the NestedScrollView
and using a LinearLayout
instead. It worked for me right away on Android Support Library v23.1.0. Here's how the layout ended up:
<android.support.design.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">
<android.support.v7.widget.Toolbar
android:id="@+id/my_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"/>
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/my_tab_layout"
android:fillViewport="false"
app:tabMode="fixed"/>
</android.support.design.widget.AppBarLayout>
<LinearLayout
android:orientation="vertical"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="4dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v4.view.ViewPager
android:id="@+id/my_view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v4.view.ViewPager>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
PS: These were actually two layout files in my project. I copied and pasted them here and tried to structure them as it would look like in a single file. I'm sorry if I screwed up while copy-pasting but please let me know if that's the case so I can fix it.
After spending hours tried all of the suggestions above, finally I made it work. The key is putting NestedScrollView
inside PageViewer
, AND set layout_behavior
to '@string/appbar_scrolling_view_behavior'
for BOTH views. The final layout is like
<CoordinatorLayout>
<ViewPager app:layout_behavior="@string/appbar_scrolling_view_behavior">
<NestedScrollView fillViewport="true" app:layout_behavior="@string/appbar_scrolling_view_behavior">
<Content>...</Content>
</NestedScrollView>
</ViewPager>
<AppBarLayout>...</AppBarLayout>
</CoordinatorLayout>
I have the same wish, nest a ViewPager
inside a NestedScrollView
. But it doesn't work for me neither. In my case, the ViewPager
is inside a Fragment
so I can switch content depending on the interactions with the drawer. Of course, AppBar, collapse, etc and all new feature of support library must work.
If a user vertically scrolls a page in the pager, I want other pages to be scrolled the same, to give the user the overall impression that the pager itself scrolled.
What I did, which works, is that I no longer embed the ViewPager
inside a NestedScrollView
, instead, I embed the content of the contained fragments inside a NestedScrollView
.
Then, in case of a scroll in one fragment, I inform the container of the new scrolling position, which stores it.
Finally, on a swipe left or right detected from the pager (using addOnPageChangeListener
looking for drag states) I inform the target left or right fragment where it must scroll (based on the container knowledge of it) to be aligned from the fragment I come from.
Use below customized class to resolve your problem. Don't forget to call onRefresh() method on pagechangelistener.
public class ContentWrappingViewPager extends ViewPager
{
private int width = 0;
public ContentWrappingViewPager(Context context) {
super(context);
}
public ContentWrappingViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int height = 0;
width = widthMeasureSpec;
if (getChildCount() > getCurrentItem()) {
View child = getChildAt(getCurrentItem());
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);
}
public void onRefresh()
{
try {
int height = 0;
if (getChildCount() > getCurrentItem()) {
View child = getChildAt(getCurrentItem());
child.measure(width, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if(h > height) height = h;
}
int heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
ViewGroup.LayoutParams layoutParams = this.getLayoutParams();
layoutParams.height = heightMeasureSpec;
this.setLayoutParams(layoutParams);
} catch (Exception e) {
e.printStackTrace();
}
}
}