滚动时Android工具栏的高程

Upv*_*ote 15 android android-toolbar android-recyclerview

我尝试在google maps android app中实现一个搜索栏:

在此输入图像描述

当回收者视图处于其初始状态时,工具栏没有高程.只有当用户开始滚动时,高程才会变得可见.搜索栏(工具栏)永远不会崩溃.这是我试图复制的内容:

<android.support.design.widget.CoordinatorLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.AppBarLayout
        android:id="@+id/appBarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="64dp">

            <!-- content -->

        </android.support.v7.widget.Toolbar>

    </android.support.design.widget.AppBarLayout>

</android.support.design.widget.CoordinatorLayout>
Run Code Online (Sandbox Code Playgroud)

在这里你可以看到结果:

在此输入图像描述

所以我的解决方案的问题是,工具栏的高程始终可见.但我希望它只在回收者视图滚动后面才会出现.设计支持库中有什么能够实现谷歌地图应用程序中的行为吗?

我在用

com.android.support:appcompat-v7:23.2.0
com.android.support:design:23.2.0
Run Code Online (Sandbox Code Playgroud)

Fai*_*ikh 37

接受的答案已过时。现在有内置功能可以做到这一点。我正在粘贴整个布局代码,以便帮助您理解。

你只需要使用CoordinatorLayoutwith AppBarLayout。这种设计模式称为Lift On Scroll并且可以通过app:liftOnScroll="true"在您的AppBarLayout.

注意:该liftOnScroll属性要求您将@string/appbar_scrolling_view_behaviorlayout_behavior 应用于滚动视图(例如NestedScrollViewRecyclerView, 等)。

<?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"
    tools:context=".MainActivity"
    android:background="@color/default_background">

    <com.google.android.material.appbar.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:liftOnScroll="true">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/default_background" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/list_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/appbar"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:orientation="vertical" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>
Run Code Online (Sandbox Code Playgroud)

参考此文档https://github.com/material-components/material-components-android/blob/master/docs/components/AppBarLayout.md


Dan*_*ann 28

无论你是否正在使用,就高程而言CoordinatorLayout,RecyclerView.OnScrollListener似乎是正确的方法.但是,根据我的经验recyclerview.getChild(0).getTop()不可靠,应该用于确定滚动状态.相反,这是有效的:

private static final int SCROLL_DIRECTION_UP = -1;
// ...
// Put this into your RecyclerView.OnScrollListener > onScrolled() method
if (recyclerview.canScrollVertically(SCROLL_DIRECTION_UP)) {
   // Remove elevation
   toolbar.setElevation(0f);
} else {
   // Show elevation
   toolbar.setElevation(50f);
}
Run Code Online (Sandbox Code Playgroud)

一定要给LayoutManager你的RecyclerView或者调用canScrollVertically分配一个可能导致崩溃!

  • 这可行,但是现在可以使用liftOnScroll轻松获得所需的功能。Doc链接:https://github.com/material-components/material-components-android/blob/master/docs/components/AppBarLayout.md (7认同)
  • 不过,@RicardoContreras liftOnScroll 并非在所有情况下都更容易。我有一个相当复杂的导航结构,而 liftOnScroll 在我的情况下实际上完全不可能实现,因为 RecyclerView 嵌套在片段和 ViewPagers 中,而 OnScrollListener 解决方案非常简单,只需进行一些代码调整。 (3认同)

Vah*_*iri 5

这是一个很好的问题,但现有的答案都不够好。getTop()绝对不建议致电,因为它非常不可靠。如果您查看遵循Material Design Refresh(2018)准则的Google应用的较新版本,它们会在开始时隐藏标高,并在用户向下滚动时立即将其添加,在用户滚动并再次到达顶部时将其再次隐藏。

我设法使用以下方法达到相同的效果:

val toolbar: android.support.v7.widget.Toolbar? = activity?.findViewById(R.id.toolbar);

recyclerView?.addOnScrollListener(object: RecyclerView.OnScrollListener() {
    override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
        super.onScrolled(recyclerView, dx, dy);

        if(toolbar == null) {
            return;
        }

        if(!recyclerView.canScrollVertically(-1)) {
            // we have reached the top of the list
            toolbar.elevation = 0f
        } else {
            // we are not at the top yet
            toolbar.elevation = 50f
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

这与垂直回收器视图(甚至其中的选项卡视图或其他回收器视图)完美配合;

一些重要的注意事项:

  • 在这里我在一个片段中这样做 activity?.findViewById...
  • 如果您的工具栏嵌套在AppBarLayout内,则应将其应用于AppBarLayout而不是将高程应用于工具栏。
  • 您应该在工具栏或AppBarLayout中添加android:elevation="0dp"app:elevation="0dp"属性,以便回收站视图的开头不具有高程。