ViewPager in NestedScrollView

I need to create an interface like Google Newsstand, which is a kind of ViewPager (horizontal scrolling) above a collapsing heading (vertical scrolling). One of my requirements is to use the new design support library introduced in Google IO 2015. ( http://android-developers.blogspot.ca/2015/05/android-design-support-library.html )

Based on the example created by Chris Banes ( https://github.com/chrisbanes/cheesesquare ), I came to the point that I can perform tough behavior, but with the basic LinearLayout (without horizontal scrolling).

I tried replacing LinearLayout with ViewPager, and I got a blank screen. I played with: width, weight and all kinds of presentation groups, but ... still a blank screen. It seems that ViewPager and NestedScrollView don't like each other.

I tried a workaround using HorizontalScrollView: it works, but I lose the advantage of the PagerTitleStrip function and focus on one panel (I can stop horizontally between 2 panels).

Now I have no more ideas if anyone can lead me to a solution ...

thank

Here is my last layout file:

<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="@dimen/header_height" android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"> <android.support.design.widget.CollapsingToolbarLayout android:layout_width="match_parent" android:layout_height="match_parent" app:contentScrim="?attr/colorPrimary" app:expandedTitleMarginEnd="64dp" app:expandedTitleMarginStart="48dp" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <include layout="@layout/part_header" android:layout_width="match_parent" android:layout_height="wrap_content" app:layout_collapseMode="parallax"/> <android.support.v7.widget.Toolbar android:id="@+id/activity_main_toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <android.support.v4.widget.NestedScrollView android:id="@+id/activity_main_nestedscrollview" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.v4.view.ViewPager android:id="@+id/activity_main_viewpager" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFA0"/> </android.support.v4.widget.NestedScrollView> </android.support.design.widget.CoordinatorLayout> 
+94
android android-layout android-viewpager android-support-library
Jun 01 '15 at 18:48
source share
19 answers

I meet this problem, I setFillViewport (true) it 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 action

  NestedScrollView scrollView = (NestedScrollView) findViewById (R.id.nest_scrollview); scrollView.setFillViewport (true); 

enter image description here

+110
Oct 28 '15 at 7:28
source share

Ok, I did a little demo with ViewPager and NestedScrollView . The problem I ran into was the height of the ViewPager and ListView . Therefore, I made a small modification when measuring the height of ListView and ViewPager's .

If someone wants to look into the code, here is the link: https://github.com/TheLittleNaruto/SupportDesignExample/

Output:

enter image description here

+67
Jul 22 '15 at 11:26
source share

Add android:fillViewport="true" to the NestedScrollView . period.

+34
Apr 11 '17 at 10:18 on
source share

There were the same problems.

When placing the NestedScrollView around the ViewPager, this will not work.

That the DID works, but puts the NestedScrollView inside the fragment layout that I load inside the ViewPager.



 <android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="fill_parent" android:layout_height="fill_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@id/fragment_detail" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="fill_vertical" android:orientation="vertical"> ...Content... </LinearLayout> </android.support.v4.widget.NestedScrollView> 

code>
+19
Jul 21 '15 at 16:07
source share

Instead of placing the ViewPager inside a NestedScrollView, do the opposite.

Place the NestedScrollView in the child views inside the ViewPager, which is essentially a fragment layout. It is also very likely that you will not even need to use NestedScrollView if the layout of the list of fragments is very simple.

Layout Examples

Action Layout:

 <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout 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:layout_height="match_parent" android:fitsSystemWindows="true"> <android.support.design.widget.AppBarLayout android:id="@+id/app_bar" android:layout_width="match_parent" android:layout_height="@dimen/app_bar_height" android:fitsSystemWindows="true" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.design.widget.CollapsingToolbarLayout android:id="@+id/toolbar_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" app:contentScrim="?attr/colorPrimary" app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"> <ImageView android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="@dimen/app_bar_height" android:scaleType="centerCrop" android:src="@drawable/my_bg" app:layout_collapseMode="parallax" app:layout_collapseParallaxMultiplier="0.8" app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed" /> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <android.support.design.widget.TabLayout android:id="@+id/content_tabs" android:layout_width="match_parent" android:layout_height="wrap_content" /> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout> </android.support.design.widget.CoordinatorLayout> 

If you don't need a TabLayout, you can cut LinearLayout and make the ViewPager standalone. But be sure to use app:layout_behavior="@string/appbar_scrolling_view_behavior" in the ViewPager attributes.

Simple fragment layout:

 <?xml version="1.0" encoding="utf-8"?> <android.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> 

Complex fragment layout:

 <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:fillViewport="true" android:layout_width="match_parent" android:layout_height="match_parent"> <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Hello World"/> </RelativeLayout> </android.support.v4.widget.NestedScrollView> 

Application Example: CollapsingToolbarPoc

enter image description here

+18
Jun 07 '16 at 8:21
source share

you can try this, the viewpager works fine, but the height of the viewpager is fixed.

I still find the best solution ... so please let me know that any moment can make it better, thanks

 <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="800dp" android:orientation="vertical"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1"/> </LinearLayout> </android.support.v4.widget.NestedScrollView> 
+14
Jun. 04 '15 at 9:15
source share

I had the same issue and I just fixed it with some changes. ViewPager does not work within NestedScrollView . Just put the ViewPager as the direct child of your CoordinatorLayout . Then the content for each fragment of the ViewPager should be enclosed in a NestedScrollView . . It is he.

+10
Sep 20 '15 at 10:43
source share

You do not need to use NestedScrollView to get parallax effects. try 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.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.design.widget.CoordinatorLayout> 
+5
Mar 07 '16 at 15:53
source share

I removed NestedScrollView from the main layout and inserted as a parent in all my layouts the Fragment that should have been loaded into the ViewPager , this was fixed for me.

+3
Feb 22 '16 at 5:42
source share

Use a custom class to solve your problem. Remember to call the onRefresh () method on the changelistener page.

 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(); } } } 
+3
Aug 16 '17 at 12:18
source share

The following should ensure the correct pager height for the view. A snippet is the first snippet provided by the view pager.

 <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent"/> <fragment class="com.mydomain.MyViewPagerFragment" android:id="@+id/myFragment" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone"/> </LinearLayout> </android.support.v4.widget.NestedScrollView> 
+2
Jun 11 '15 at 6:23
source share

I had a similar problem (but without CollapsingToolbarLayout , just Toolbar + TabLayout in AppBarLayout ). I wanted the toolbar to scroll out of view while scrolling the contents of the ViewPager within the NestedScrollView .

There was something like this in my layout:

 <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 did not work properly, but I decided to just get rid of NestedScrollView and use LinearLayout . It immediately worked for me in Android Support Library v23.1.0. Here's how the design ended:

 <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: In fact, these were two layout files in my project. I copied and pasted them here and tried to structure them, as it would in a single file. I apologize if I screwed up when copying, but please let me know if this is the case, I can fix it.

+2
Oct 23 '15 at 20:18
source share

I had a layout with an application toolbar with a NestedScrollView below it, then inside the nested toolbar there was LinearLayout, below LinearLayout there was a presentation pager. The idea was that the LinearLayout inside the NestedScrollView was fixed - you could slide left / right between the views of the view pager, but this content did not move at least horizontally. You can still scroll all the contents vertically due to the nested scroll view. It was an idea. So I set the NestedScrollView nested height to match_parent, ran viewport, then all the child layouts / ViewPager for wrap_content.

It was right in my head. But that didn’t work - ViewPager allowed me to go left / right, but there is no vertical scrolling, whether the content of the page in the view is pushed below the bottom of the current screen or not. It turns out that this was mainly because ViewPager does not consider wrap_content on different pages.

I went around this by subclassing the ViewPager so that it changes height depending on the currently selected item, and this makes it behave like layout_height = "wrap_content":

 public class ContentWrappingViewPager extends ViewPager { 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; 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); } } 

The solution was inspired by this answer . Worked for me!

+2
Feb 24 '17 at 17:56 on
source share

I have the same desire, a ViewPager inside a NestedScrollView . But for me, this does not work either. In my case, the ViewPager is inside the Fragment , so I can switch the content depending on the interaction with the box. Of course, AppBar, collapse, etc. And all the new support library features should work.

If the user vertically scrolls the page in the pager, I want the other pages to scroll the same way, to give the user a general impression that the pager itself is scrolling.

What I did, what works, is that I no longer insert the ViewPager inside a NestedScrollView , instead I insert the contents of the contained fragments inside the NestedScrollView .

Then, in the case of scrolling in one fragment, I inform the container about the new scroll position that stores it.

Finally, when scrolling left or right on a pager (using addOnPageChangeListener to search for drag states), I inform the target left or right fragment where it should scroll (based on the knowledge of the container), which should be aligned from the fragment from which I came .

+1
Jun 17 '15 at 21:02
source share

I know one working solution: you use Activity, with CoordinatorLayout and use FrameLayout, a container. Then. use the fragment manager to place the fragment in the container. For example, my code is:

 <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.design.widget.AppBarLayout android:id="@+id/appbar" android:layout_width="match_parent" android:layout_height="wrap_content" app:elevation="0dp"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" app:layout_scrollFlags="scroll|enterAlways" android:layout_height="@dimen/toolbar_height" android:background="?attr/colorPrimary" android:gravity="center"> </android.support.v7.widget.Toolbar> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" app:layout_behavior="@string/appbar_scrolling_view_behavior"> </FrameLayout> 

And a fragment:

 <LinearLayout 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:layout_height="match_parent" android:orientation="vertical" tools:context="com.improvemdia.inmyroom.MainFragment"> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent" /> 

Then use the FragmentManager

 getSupportFragmentManager().beginTransaction() .replace(R.id.container, new MainFragment()) .commit(); 
0
Oct 15 '15 at 18:10
source share

After spending hours, I tried all of the above suggestions, finally, I earned. The key is to put the NestedScrollView inside the PageViewer , and set layout_behavior to '@string/appbar_scrolling_view_behavior' for BOTH . The final layout is similar to

 <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> 
0
Nov 07 '15 at 2:41
source share

you just uninstalled NestedScrollView into your xml and added this code to your class

yourGridView.setNestedScrollingEnabled(true);

0
May 15, '17 at 15:25
source share

In fact, NestedScrollView should not be a direct relative of the CollapsingToolbarLayout in CoordinatorLayout. I have achieved something real bizzare. The appbar_scrolling_view_behavior application works with two nested fragments.

My activity layout:

 <android.support.design.widget.CoordinatorLayout> <android.support.design.widget.AppBarLayout> <android.support.design.widget.CollapsingToolbarLayout> <include layout="@layout/toolbar"/> </android.support.design.widget.CollapsingToolbarLayout> </android.support.design.widget.AppBarLayout> <FrameLayout android:id="@+id/container" app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </android.support.design.widget.CoordinatorLayout> 

In the “container” frameLayout, I inflated this fragment:

 <android.support.constraint.ConstraintLayout> ... some content ... <android.support.v4.view.ViewPager/> ... </android.support.constraint.ConstraintLayout> 

And the fragments inside this ViewPager look like this:

 <RelativeLayout> <android.support.v7.widget.RecyclerView/> .... </RelativeLayout> 

The fact that NestedScrollView can be so deep in the hierarchy of CoordinatorLayout children and scroll behavior that the work really surprised me.

0
Aug 21 '17 at 21:00
source share

just put this line in NestedScrollView

 android:fillViewport="true" 
0
May 25 '19 at
source share



All Articles