在 Android 中使用 Sticky Header 创建 ListView 视差效果

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

一个带有代码片段的快速 Android 示例,用于演示如何创建带有粘性标题的 ListView 视差效果。在我们之前的教程中,我展示了如何 创建 ListView 标题视差动画 。现在在这个例子中,我们将更进一步,制作列表标题视差动画,当列表滚动时,视图会停留在顶部。

您需要按照下面描述的以下步骤来创建列表视图视差效果。

您可以在以下视频中看到它的样子。


1.声明活动布局

首先让我们开始声明您的活动布局。这有点棘手。让我们采用承载英雄图像、粘性视图和 ListView 的框架布局。


 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
&lt;ImageView
    android:id="@+id/heroImageView"
    android:layout_width="match_parent"
    android:layout_height="250dp"
    android:background="@drawable/wallpaper"
    android:scaleType="fitCenter" /&gt;

&lt;ListView
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:divider="#9E9E9E"
    android:dividerHeight="1dp"
    android:scrollbars="none"&gt;&lt;/ListView&gt;

&lt;TextView
    android:id="@+id/stickyView"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#222"
    android:gravity="center_vertical"
    android:paddingLeft="10dp"
    android:text="Heading1"
    android:textColor="#fff"
    android:textSize="20sp"
    android:textStyle="bold" /&gt;

</FrameLayout>

以下屏幕截图描述了我们的活动布局是如何定义的。

2.声明列表标题布局

现在声明列表标题的布局。在这个例子中,我在 FrameLayout 中声明了一个 ImageView 。标题视图声明如下。


 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
&lt;ImageView
    android:id="@+id/heroImageView"
    android:layout_width="match_parent"
    android:layout_height="250dp"
    android:background="@drawable/wallpaper"
    android:scaleType="fitCenter" /&gt;

&lt;ListView
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:divider="#9E9E9E"
    android:dividerHeight="1dp"
    android:scrollbars="none"&gt;&lt;/ListView&gt;

&lt;TextView
    android:id="@+id/stickyView"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#222"
    android:gravity="center_vertical"
    android:paddingLeft="10dp"
    android:text="Heading1"
    android:textColor="#fff"
    android:textSize="20sp"
    android:textStyle="bold" /&gt;

</FrameLayout>

请注意,在上面的标题布局中,

  • 我们已经声明了 Space 对象。 Android Space widget 是 View 的子类,用于占据屏幕上不可见的透明空间。您不能应用任何样式,例如颜色、背景等。
  • 两个 Space 对象的高度与活动布局中声明的主图和粘性小部件的高度相同。
  • 这两个不可见视图将有助于计算视图位置并有助于创建平行效果。

3.声明列表行布局

为您的列表视图行声明另一个布局。在此示例中,为了简单起见,我声明了一个简单的 TextView 。您可以通过声明您自己的自定义适配器来设计您选择的奇特列表。


 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
&lt;ImageView
    android:id="@+id/heroImageView"
    android:layout_width="match_parent"
    android:layout_height="250dp"
    android:background="@drawable/wallpaper"
    android:scaleType="fitCenter" /&gt;

&lt;ListView
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:divider="#9E9E9E"
    android:dividerHeight="1dp"
    android:scrollbars="none"&gt;&lt;/ListView&gt;

&lt;TextView
    android:id="@+id/stickyView"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#222"
    android:gravity="center_vertical"
    android:paddingLeft="10dp"
    android:text="Heading1"
    android:textColor="#fff"
    android:textSize="20sp"
    android:textStyle="bold" /&gt;

</FrameLayout>

4.处理ListView滚动事件

以下步骤将指导您在活动中创建列表视图、添加列表标题和实现视差效果所需的必要事项。

  • 为您的列表视图实现 setOnScrollListener 以处理用户滚动事件。

  • 根据ListView中第一项的位置计算出sticky header view的位置。

  • 当第一项已经到达顶部时,您不需要重新定位粘性标题视图。

  • 设置英雄图像滚动到 ListView 的一半量


 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
&lt;ImageView
    android:id="@+id/heroImageView"
    android:layout_width="match_parent"
    android:layout_height="250dp"
    android:background="@drawable/wallpaper"
    android:scaleType="fitCenter" /&gt;

&lt;ListView
    android:id="@+id/listView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:divider="#9E9E9E"
    android:dividerHeight="1dp"
    android:scrollbars="none"&gt;&lt;/ListView&gt;

&lt;TextView
    android:id="@+id/stickyView"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:background="#222"
    android:gravity="center_vertical"
    android:paddingLeft="10dp"
    android:text="Heading1"
    android:textColor="#fff"
    android:textSize="20sp"
    android:textStyle="bold" /&gt;

</FrameLayout>

在此处从 Github 下载此项目的源代码。