NestedScrollView中的ViewPager

我需要创build一个像Google Newsstand这样的界面,它是一种在折叠标题(垂直滚动)上的ViewPager(水平滚动)。 我的要求之一是使用Google IO 2015中提供的新devise支持库( http://android-developers.blogspot.ca/2015/05/android-design-support-library.html )

基于由Chris Banes( https://github.com/chrisbanes/cheesesquare )创build的示例,我已经达到了能够使用基本LinearLayout(无水平滚动)进行折叠行为的要点。

我试图用ViewPagerreplaceLinearLayout,然后我得到一个空白的屏幕。 我玩的宽度,重量和各种观点组,但….仍然是一个空白的屏幕。 看来,ViewPager和NestedScrollView不喜欢对方。

我通过使用Horizo​​ntalScrollView尝试了一种解决方法:它可以工作,但是我放松了PagerTitleStripfunction的好处,并且关注单个面板(我可以在2个面板之间水平停​​止)。

现在我没有更多的想法,如果任何人都可以让我find一个解决scheme…

谢谢

这是我最新的布局文件:

<?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> 

我遇到了这个问题,我通过setFillViewport (true)解决了它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"/> 

在活动中

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

在这里输入图像说明

好的,我用ViewPagerNestedScrollView做了一个小演示。 我面临的问题是ViewPagerListView的高度。 所以我在ListViewViewPager's高度测量上做了一些修改。

如果有人想看看代码,这里是链接: https : //github.com/TheLittleNaruto/SupportDesignExample/

输出:

在这里输入图像说明

有相同的问题。

在ViewPager 周围放置NestedScrollView时,它不起作用。

DID的工作原理是将NestedScrollView 放入我在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> 

你可以这样尝试,viewpager工作正常,但viewpager的高度是固定的。

我仍然find更好的解决scheme,所以请让我知道任何一点可以做得更好,谢谢

 <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> 

NestedScrollView添加android:fillViewport="true" 。 期。

我有同样的问题,只是修改了一些变化。 ViewPagerNestedScrollView 。 简单地把你的ViewPager作为你的CoordinatorLayout的直接子。 然后,每个ViewPager的片段内容应该包含在NestedScrollView 而已。

而不是将ViewPager放在NestedScrollView中,反之亦然。

将NestedScrollView放置在ViewPager中的子View中,实质上就是Fragment的布局。 如果你的Fragment的列表布局非常简单,你甚至不需要使用NestedScrollView。

示例布局

活动的布局:

 <?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> 

如果你不需要TabLayout,你可以消除LinearLayout并使ViewPager独立。 但是一定要在ViewPager属性中使用app:layout_behavior="@string/appbar_scrolling_view_behavior"

简单的片段布局:

 <?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" /> 

复杂片段的布局:

 <?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> 

示例应用程序: CollapsingToolbarPoc

在这里输入图像说明

你不需要使用NestedScrollView来产生视差效果。 尝试这样的事情:

 <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> 

我从主布局中删除了NestedScrollView ,并在所有我应该在ViewPager中加载的Fragment布局中插入Parent作为Parent ,为我解决了这个问题。

以下应确保视图寻呼机的适当高度。 该片段是视图寻呼机提供的第一个片段。

 <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> 

我有一个类似的问题(但没有CollapsingToolbarLayout ,只是一个简单的Toolbar +在TabLayout内的AppBarLayout )。 当向下滚动ViewPager中的NestedScrollView的内容时,我想让工具栏滚动视线。

我的布局是这样的:

 <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> 

这个布局并没有像预期的那样工作,但是我通过简单地去掉NestedScrollView并使用LinearLayout来解决这个问题。 它立即在Android支持库v23.1.0上为我工作。 以下是布局结束的方式:

 <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:这些实际上是我的项目中的两个布局文件。 我将它们复制并粘贴到这里,并试图将它们组织成一个文件。 对不起,如果我搞砸了复制粘贴,但请让我知道如果是这样的话,我可以修复它。

我有一个应用程序工具栏与下面的NestedScrollView的布局,然后嵌套工具栏内部是一个LinearLayout,在LinearLayout下面是一个视图寻呼机。 想法是NestedScrollView里面的LinearLayout是固定的 – 你可以在视图传呼机的视图之间左右滑动,但是这个内容至less水平移动。 由于嵌套滚动视图,您仍然应该能够垂直滚动所有内容。 这是这个想法。 所以我设置嵌套NestedScrollView高度match_parent,填充视口,然后所有的孩子布局/ ViewPager wrap_content。

在我的脑海中,这是对的。 但它不起作用 – ViewPager允许我去左/右,但没有垂直滚动,无论viewpager页面内容是否推到当前屏幕底部以下。 事实certificate,这基本上是因为ViewPager不尊重wrap_content各个页面。

我通过inheritance了ViewPager来改变高度,取决于当前select的项目,强制它的行为类似于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); } } 

解决scheme受到这个答案的启发。 为我工作!

我有同样的愿望,在ViewPager嵌套一个NestedScrollView 。 但这对我也不起作用。 在我的情况下, ViewPager是在一个Fragment所以我可以切换内容取决于与抽屉的交互。 当然,AppBar,崩溃等支持库的所有新function都必须工作。

如果用户在寻呼机中垂直滚动页面,我希望其他页面滚动相同,以给用户整个页面滚动本身的印象。

我所做的工作是,我不再将ViewPagerembedded到NestedScrollView ,而是将包含的片段的内容embedded到NestedScrollView

然后,在一个片段中滚动的情况下,我通知容器存储它的新的滚动位置。

最后,从寻呼机检测到的左右滑动(使用addOnPageChangeListener查找拖动状态),我通知目标左边或右边的片段,它必须滚动(基于容器的知识),以便从我来自的片段alignment。

我知道一个工作解决scheme:你使用Activity,使用CoordinatorLayout并使用FrameLayout,容器。 然后。 使用片段pipe理器将片段放入容器中。 例如我的代码:

 <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> 

和片段:

 <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" /> 

然后使用FragmentManager

 getSupportFragmentManager().beginTransaction() .replace(R.id.container, new MainFragment()) .commit(); 

花了几个小时尝试了上面所有的build议后,终于做到了。 关键是将NestedScrollView放入PageViewer ,并将NestedScrollView设置为'@string/appbar_scrolling_view_behavior'以获得BOTH视图。 最终的布局就像

 <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> 

你只需在你的xml中移除NestedScrollView ,并在你的类中添加这个代码

yourGridView.setNestedScrollingEnabled(true);

使用下面的自定义类来解决您的问题。 不要忘记在pagechangelistener上调用onRefresh()方法。

 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(); } } } 

实际上NestedScrollView不需要是CoordinatorLayout中的CollapsingToolbarLayout的直接兄弟。 我已经实现了一些真正的bizzare。 appbar_scrolling_view_behavior在2个嵌套片段中工作。

我的活动布局:

 <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> 

在“容器”frameLayout我夸大了这个片段:

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

这个ViewPager里面的片段如下所示:

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

事实上,NestedScrollView可以在CoordinatorLayout的子层次结构和滚动行为stil工程如此深入惊讶我。