CollapsingToolbarLayout 导致 RecyclerView 底部在屏幕下方
CollapsingToolbarLayout causes RecyclerView's bottom to be underscreen
我有固定高度 (@dimen/app_bar_height = 200dp) 的 AppBarLayout,其中有 CollapsingToolbarLayout。向下滚动时,部分recyclerview隐藏在屏幕底部。
如果我删除滚动标志(即禁用滚动折叠)我从 CollapsingToolbarLayout 中删除 app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
然后它通常对齐屏幕底部。
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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"
tools:ignore="MergeRootFrame">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<!-- Problem HERE in app:layout_scrollFlags -->
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:expandedTitleGravity="bottom"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:toolbarId="@+id/toolbar">
<TextView
android:text="Hello, Hello, Hello, Hello, Hello, Hello, Hello, Hello, Hello, Hello"
android:textSize="19sp"
android:textStyle="bold"
android:id="@+id/txtDescr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.5"/>
<androidx.appcompat.widget.Toolbar
android:id="@+id/detail_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
android:layout_margin="@dimen/fab_margin"
app:layout_collapseMode="pin"
app:srcCompat="@android:drawable/stat_notify_chat" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:scrollbarThumbVertical="@android:color/darker_gray"
android:scrollbarSize="7dp"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
多次尝试您的代码,但没有成功。终于找到了解决方法。只需将要固定在顶部的视图高度作为 margin-bottom 添加到 recyclerView,保持 recyclerView 的高度为 wrap_content。
例如。如果你想固定你的工具栏然后将它的高度作为边距底部添加到回收器视图
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:scrollbarThumbVertical="@android:color/darker_gray"
android:scrollbarSize="7dp"
android:layout_height="wrap_content"
android:layout_marginBottom="?attr/actionBarSize"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
希望这能解决您的问题。
向下滚动 recycleview 时....如果您不想要工具栏,因为 recycleview 隐藏在工具栏后面....
使用这个 --> app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
因此您的折叠工具栏布局代码将是-->
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="350dp"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleTextAppearance="@android:color/transparent"
android:fitsSystemWindows="true"
>
我最终使用以下方法来检测最后一项滚动和 notifyDataSetChanged(),这解决了问题:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
private boolean hasFixedLastItemNotVisible = false;
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!hasFixedLastItemNotVisible &&
!recyclerView.canScrollVertically(10) &&
newState==RecyclerView.SCROLL_STATE_IDLE) {
hasFixedLastItemNotVisible = true;
recyclerView.getAdapter().notifyDataSetChanged();
}
}
});
我的猜测是您在 CoordinatorLayout 完成测量 AppbarLayout 之前过早地加载 RecyclerView 中的项目。如果您的 onViewCreated
中的项目列表立即可用并且您立即创建并分配适配器,则可能会发生这种情况。
我不知道你是如何在你的代码中设置你的 RecyclerView 的,但我遇到了同样的问题,我通过使用 View.post(Runnable)
:
解决了它
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val adapter = MyAdapter(viewModel.items)
// replace:
// recyclerView.adapter = adapter
// with:
view.post { recyclerView.adapter = adapter }
}
另请注意,如果您碰巧使用了 ListAdapter 的子类,它与主线程异步工作,实际上您可能不会遇到此问题。
我有固定高度 (@dimen/app_bar_height = 200dp) 的 AppBarLayout,其中有 CollapsingToolbarLayout。向下滚动时,部分recyclerview隐藏在屏幕底部。
如果我删除滚动标志(即禁用滚动折叠)我从 CollapsingToolbarLayout 中删除 app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
然后它通常对齐屏幕底部。
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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"
tools:ignore="MergeRootFrame">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<!-- Problem HERE in app:layout_scrollFlags -->
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:expandedTitleGravity="bottom"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
app:toolbarId="@+id/toolbar">
<TextView
android:text="Hello, Hello, Hello, Hello, Hello, Hello, Hello, Hello, Hello, Hello"
android:textSize="19sp"
android:textStyle="bold"
android:id="@+id/txtDescr"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.5"/>
<androidx.appcompat.widget.Toolbar
android:id="@+id/detail_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|start"
android:layout_margin="@dimen/fab_margin"
app:layout_collapseMode="pin"
app:srcCompat="@android:drawable/stat_notify_chat" />
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:scrollbarThumbVertical="@android:color/darker_gray"
android:scrollbarSize="7dp"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
多次尝试您的代码,但没有成功。终于找到了解决方法。只需将要固定在顶部的视图高度作为 margin-bottom 添加到 recyclerView,保持 recyclerView 的高度为 wrap_content。
例如。如果你想固定你的工具栏然后将它的高度作为边距底部添加到回收器视图
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:scrollbars="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:scrollbarThumbVertical="@android:color/darker_gray"
android:scrollbarSize="7dp"
android:layout_height="wrap_content"
android:layout_marginBottom="?attr/actionBarSize"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
希望这能解决您的问题。
向下滚动 recycleview 时....如果您不想要工具栏,因为 recycleview 隐藏在工具栏后面....
使用这个 --> app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
因此您的折叠工具栏布局代码将是-->
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="350dp"
app:layout_scrollFlags="scroll|enterAlways|enterAlwaysCollapsed"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleTextAppearance="@android:color/transparent"
android:fitsSystemWindows="true"
>
我最终使用以下方法来检测最后一项滚动和 notifyDataSetChanged(),这解决了问题:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
private boolean hasFixedLastItemNotVisible = false;
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
if (!hasFixedLastItemNotVisible &&
!recyclerView.canScrollVertically(10) &&
newState==RecyclerView.SCROLL_STATE_IDLE) {
hasFixedLastItemNotVisible = true;
recyclerView.getAdapter().notifyDataSetChanged();
}
}
});
我的猜测是您在 CoordinatorLayout 完成测量 AppbarLayout 之前过早地加载 RecyclerView 中的项目。如果您的 onViewCreated
中的项目列表立即可用并且您立即创建并分配适配器,则可能会发生这种情况。
我不知道你是如何在你的代码中设置你的 RecyclerView 的,但我遇到了同样的问题,我通过使用 View.post(Runnable)
:
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val adapter = MyAdapter(viewModel.items)
// replace:
// recyclerView.adapter = adapter
// with:
view.post { recyclerView.adapter = adapter }
}
另请注意,如果您碰巧使用了 ListAdapter 的子类,它与主线程异步工作,实际上您可能不会遇到此问题。