I have a classic layout with a ToolBar on the top, a TabLayout below it, and a ViewPager switching tabs from the TabLayout. When content in the ViewPager is scrollable, the ToolBar should scroll out of sight, and the TabLayout should follow and stick when it reaches the top.
我有一个经典的布局,顶部有一个ToolBar,下面有一个TabLayout,还有一个来自TabLayout的ViewPager切换标签。当ViewPager中的内容可滚动时,工具栏应该滚动到视线之外,TabLayout应该跟随并在它到达顶部时粘住。
All this is good in my current code, except, the ToolBar is always scrollable, regardless of the size of the ViewPager's content. See my code below. Any brilliant ideas on how to fix this?
所有这些在我当前的代码中都很好,除了ToolBar总是可滚动的,无论ViewPager的内容大小如何。请参阅下面的代码。关于如何解决这个问题的任何好主意?
<?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:orientation="vertical">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/primary"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.ToolBar"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:scrollbars="horizontal"
app:tabIndicatorColor="@color/black_text" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/tabs_activity_view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
EDIT:
I can see that the viewPager's height is the same as the height for the entire root view. This might be intentded, as the appbar_scrolling_view_behavior does seem to add a top and bottom offset. It does however seem weird, since it will result in always scrolling the toolbar and tabbar.
我可以看到viewPager的高度与整个根视图的高度相同。这可能是有意的,因为appbar_scrolling_view_behavior似乎确实添加了顶部和底部偏移。但它看起来很奇怪,因为它会导致始终滚动工具栏和标签栏。
8 个解决方案
#1
4
I suggested you try this sample.
我建议你试试这个样本。
this is a layout like your layout in the sample.
这是一个类似于样本布局的布局。
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_done" />
</android.support.design.widget.CoordinatorLayout>
#2
3
I have solved the issue, tried over the example Google template and find out that
我已经解决了这个问题,尝试了Google模板示例并找出了解决方法
app:layout_behavior="@string/appbar_scrolling_view_behavior"
line must be added into view pager properties xml. It solved my problem.
必须将行添加到视图分页器属性xml中。它解决了我的问题。
#3
1
using ListView as the data for ViewPager? If so, you need listView.setNestedScrollingEnabled(true);
使用ListView作为ViewPager的数据?如果是这样,你需要listView.setNestedScrollingEnabled(true);
#4
0
Try adding these attributes on TabLayout:
尝试在TabLayout上添加这些属性:
app:layout_collapseMode="pin"
app:tabMode="fixed"
And this on AppBarLayout:
这个在AppBarLayout上:
android:fitsSystemWindows="true"
* UPDATE *
*更新*
I tried and this is not enough, since toolbar is still scrollable. The solution is to make some logic about ViewPager (and its content).
我试过,这还不够,因为工具栏仍然是可滚动的。解决方案是制定一些关于ViewPager(及其内容)的逻辑。
Remove from xml layout file the toolbar scroll_flag attribute. You have to implement some java code to check if ViewPager content height is > then screenHeight - (toolbar + tabBar). If true, set programmatically the scroll_flags as this:
从xml布局文件中删除工具栏scroll_flag属性。你必须实现一些java代码来检查ViewPager的内容高度是否> screenHeight - (toolbar + tabBar)。如果为true,则以编程方式将scroll_flags设置为:
LayoutParams params;
params = // get layout params from your toolbar
params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
| AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
// set params
toolbar.setLayoutParams(params);
#5
0
The ViewPager
height should be match_parent
and not wrap_content
.
ViewPager高度应该是match_parent而不是wrap_content。
#6
0
Based on other samples, my own code, and the (somewhat messy) source code of the appbar_scrolling_view_behavior:
基于其他示例,我自己的代码,以及appbar_scrolling_view_behavior的(有点混乱)源代码:
public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
View dependency) {
final CoordinatorLayout.Behavior behavior =
((CoordinatorLayout.LayoutParams) dependency.getLayoutParams()).getBehavior();
if (behavior instanceof Behavior) {
// Offset the child so that it is below the app-bar (with any overlap)
final int appBarOffset = ((Behavior) behavior)
.getTopBottomOffsetForScrollingSibling();
final int expandedMax = dependency.getHeight() - mOverlayTop;
final int collapsedMin = parent.getHeight() - child.getHeight();
if (mOverlayTop != 0 && dependency instanceof AppBarLayout) {
// If we have an overlap top, and the dependency is an AppBarLayout, we control
// the offset ourselves based on the appbar's scroll progress. This is so that
// the scroll happens sequentially rather than linearly
final int scrollRange = ((AppBarLayout) dependency).getTotalScrollRange();
setTopAndBottomOffset(AnimationUtils.lerp(expandedMax, collapsedMin,
Math.abs(appBarOffset) / (float) scrollRange));
} else {
setTopAndBottomOffset(dependency.getHeight() - mOverlayTop + appBarOffset);
}
}
return false;
}
I'm reading this in a way explaining the problem, as this is expected behavior with this code.
我正在以解释问题的方式阅读本文,因为这是此代码的预期行为。
I think we need to write our own scroll behavior, specially for the RecyclerView,
我认为我们需要编写自己的滚动行为,特别是对于RecyclerView,
#7
0
i've just had the same problem. The solution is very simple, just set your viewpager height
我刚遇到同样的问题。解决方案非常简单,只需设置您的viewpager高度即可
android:layout_height="wrap_content"
#8
-1
Simple solution is - wrap your appbar layour and page viewer with a relative layout. - give your appbar layout some id - in page view set android:layout_below="Your_appbar_layout" Eg:
简单的解决方案是 - 使用相对布局包装您的appbar layour和页面查看器。 - 给你的appbar布局一些id - 在页面视图中设置android:layout_below =“Your_appbar_layout”例如:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/your_appBar_ID"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/primary"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.ToolBar"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:scrollbars="horizontal"
app:tabIndicatorColor="@color/black_text" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/tabs_activity_view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/your_appBar_ID"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</RelativeLayout>
#1
4
I suggested you try this sample.
我建议你试试这个样本。
this is a layout like your layout in the sample.
这是一个类似于样本布局的布局。
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="@dimen/fab_margin"
android:src="@drawable/ic_done" />
</android.support.design.widget.CoordinatorLayout>
#2
3
I have solved the issue, tried over the example Google template and find out that
我已经解决了这个问题,尝试了Google模板示例并找出了解决方法
app:layout_behavior="@string/appbar_scrolling_view_behavior"
line must be added into view pager properties xml. It solved my problem.
必须将行添加到视图分页器属性xml中。它解决了我的问题。
#3
1
using ListView as the data for ViewPager? If so, you need listView.setNestedScrollingEnabled(true);
使用ListView作为ViewPager的数据?如果是这样,你需要listView.setNestedScrollingEnabled(true);
#4
0
Try adding these attributes on TabLayout:
尝试在TabLayout上添加这些属性:
app:layout_collapseMode="pin"
app:tabMode="fixed"
And this on AppBarLayout:
这个在AppBarLayout上:
android:fitsSystemWindows="true"
* UPDATE *
*更新*
I tried and this is not enough, since toolbar is still scrollable. The solution is to make some logic about ViewPager (and its content).
我试过,这还不够,因为工具栏仍然是可滚动的。解决方案是制定一些关于ViewPager(及其内容)的逻辑。
Remove from xml layout file the toolbar scroll_flag attribute. You have to implement some java code to check if ViewPager content height is > then screenHeight - (toolbar + tabBar). If true, set programmatically the scroll_flags as this:
从xml布局文件中删除工具栏scroll_flag属性。你必须实现一些java代码来检查ViewPager的内容高度是否> screenHeight - (toolbar + tabBar)。如果为true,则以编程方式将scroll_flags设置为:
LayoutParams params;
params = // get layout params from your toolbar
params.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
| AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);
// set params
toolbar.setLayoutParams(params);
#5
0
The ViewPager
height should be match_parent
and not wrap_content
.
ViewPager高度应该是match_parent而不是wrap_content。
#6
0
Based on other samples, my own code, and the (somewhat messy) source code of the appbar_scrolling_view_behavior:
基于其他示例,我自己的代码,以及appbar_scrolling_view_behavior的(有点混乱)源代码:
public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
View dependency) {
final CoordinatorLayout.Behavior behavior =
((CoordinatorLayout.LayoutParams) dependency.getLayoutParams()).getBehavior();
if (behavior instanceof Behavior) {
// Offset the child so that it is below the app-bar (with any overlap)
final int appBarOffset = ((Behavior) behavior)
.getTopBottomOffsetForScrollingSibling();
final int expandedMax = dependency.getHeight() - mOverlayTop;
final int collapsedMin = parent.getHeight() - child.getHeight();
if (mOverlayTop != 0 && dependency instanceof AppBarLayout) {
// If we have an overlap top, and the dependency is an AppBarLayout, we control
// the offset ourselves based on the appbar's scroll progress. This is so that
// the scroll happens sequentially rather than linearly
final int scrollRange = ((AppBarLayout) dependency).getTotalScrollRange();
setTopAndBottomOffset(AnimationUtils.lerp(expandedMax, collapsedMin,
Math.abs(appBarOffset) / (float) scrollRange));
} else {
setTopAndBottomOffset(dependency.getHeight() - mOverlayTop + appBarOffset);
}
}
return false;
}
I'm reading this in a way explaining the problem, as this is expected behavior with this code.
我正在以解释问题的方式阅读本文,因为这是此代码的预期行为。
I think we need to write our own scroll behavior, specially for the RecyclerView,
我认为我们需要编写自己的滚动行为,特别是对于RecyclerView,
#7
0
i've just had the same problem. The solution is very simple, just set your viewpager height
我刚遇到同样的问题。解决方案非常简单,只需设置您的viewpager高度即可
android:layout_height="wrap_content"
#8
-1
Simple solution is - wrap your appbar layour and page viewer with a relative layout. - give your appbar layout some id - in page view set android:layout_below="Your_appbar_layout" Eg:
简单的解决方案是 - 使用相对布局包装您的appbar layour和页面查看器。 - 给你的appbar布局一些id - 在页面视图中设置android:layout_below =“Your_appbar_layout”例如:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/your_appBar_ID"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/primary"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/AppTheme.ToolBar"
app:layout_scrollFlags="scroll|enterAlways" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:scrollbars="horizontal"
app:tabIndicatorColor="@color/black_text" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/tabs_activity_view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/your_appBar_ID"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</RelativeLayout>