Material Design 的 RecyclerView 详解与实践

前言

Material Design 是谷歌在 2014 年推出的一种视觉设计语言,旨在提供一种更加现代、统一、直观和有信息等级感的用户体验。它不仅仅是一种设计语言,还是一种视觉和交互的规范,涉及到 UI 元素、布局、颜色、字体、动画、阴影等各个方面。

在前端开发中,实现 Material Design 可以帮助您在设计上得到更统一、更高质量的用户体验,同时还可以提高开发效率和代码质量。本文将介绍 RecyclerView,这个在 Material Design 中被广泛使用的控件。

什么是 RecyclerView

RecyclerView 是一个强大而灵活的控件,是 Android 5.0(API 级别 21)中的一个新特性,取代了 ListView 和 GridView,并提供了默认的动画效果。它可以用于展示大量数据条目,并支持滚动、布局管理和触摸交互等特性,同时具有更好的性能和可扩展性。

与 ListView 和 GridView 相比,RecyclerView 更加模块化,可以将数据管理、布局管理、视图呈现和用户交互分开处理,实现高度的复用和扩展。它提供了一个可视化的布局管理器(LayoutManager)来定位子视图的位置和大小,可以支持线性、网格、瀑布流等多种布局方式。此外,RecyclerView 还提供了拖拽排序、滑动删除、动态变化等高级功能,可以帮助您更好地实现交互效果。

RecyclerView 的基本使用

添加依赖

在构建.gradle文件中添加依赖:

------------ -
    -------------- --------------------------------------------
-

准备数据

假设我们要展示一个包含图片和文字的列表条目。首先定义一个数据类 Item:

---- ----- -------- ------ ------- --- --------- -------

接下来定义一个数据源,包含若干个 Item:

--- ----- - -------
    -------------- --------------------------------------------------------------------------------------
    ---------------- -------------------------------------------------------
    --------------- -------------------------------------------------
    ---------------- ------------------------------------------------------------------------
    ----------------- -------------------------------------------------------------------------------
-

创建布局

接下来,我们需要创建一个列表条目的布局,它包含一个 ImageView 和一个 TextView,使用 LinearLayout 作为根布局:

------------- ----------------------------------------------------------
              -----------------------------------
              ------------------------------------
              ---------------------
              ---------------------------------

    ----------
        ----------------------------
        ---------------------------
        ----------------------------
        --------------------------------

    ---------
        ----------------------------
        --------------------------
        ------------------------------------
        -------------------------
        -----------------------
        ---------------------------------
        ----------------------------------

---------------

创建适配器

适配器(Adapter)是 RecyclerView 的一个关键组件,它提供了将数据绑定到视图的方法,并管理了列表条目的创建、更新和删除。我们需要定义一个适配器,将数据源中的每个 Item 显示到列表中。

先创建一个 ViewHolder,用于缓存视图中的各个控件:

----- -------------------- ----- - ----------------------------- -
    --- ------ --------- - ----------------------------------
    --- ------ -------- - ----------------------------------
-

然后创建一个适配器类,实现 onCreateViewHolder、onBindViewHolder 和 getItemCount 三个方法:

----- ------------------- --- ------ ----------- - -------------------------------------- -

    -------- --- -------------------------- ---------- --------- ----- -------------- -
        --- ---- - ----------------------------------------------------------------- ------- ------
        ------ --------------------
    -

    -------- --- ------------------------ --------------- --------- ---- -
        --- ---- - ---------------
        ----------------- - ----------
        ---------------------------------------------------------------
    -

    -------- --- --------------- --- -
        ------ ----------
    -
-

其中,onCreateViewHolder 方法用于创建 ViewHolder,onBindViewHolder 方法用于将数据绑定到视图中,getItemCount 方法用于返回数据源的总数。

设置布局管理器和适配器

最后,在 Activity 或 Fragment 中使用 RecyclerView,设置一个布局管理器和一个适配器。布局管理器可以用来管理列表条目的位置和大小,适配器则负责展示数据和更新视图。

----- ------------ - ------------------- -

    -------- --- ---------------------------- -------- -
        ----------------------------------
        --------------------------------------

        --- ------------- - -------------------------
        -------------------------- - -------------

        --- ------- - ------------------
        -------------------- - -------
    -
-

至此,我们已经完成了 RecyclerView 的基本使用。

RecyclerView 的进阶使用

使用 DiffUtil

在实际开发中,我们经常需要对数据进行增删改查等操作,然后刷新列表以更新视图。RecyclerView 提供了默认的动画效果,但是如果数据量较大,这种操作可能会导致页面卡顿或ANR。

为了避免这种情况,谷歌提供了一个 DiffUtil 工具类,可以比较两个数据列表的差异,并以最小化的代价更新 RecyclerView 的数据和视图。DiffUtil 可以在后台线程中运行,不会影响主线程的流畅度,同时还可以提高列表的渲染效率。

使用 DiffUtil 需要完成以下步骤:

  • 定义一个数据类,将 Item 和它在列表中的位置组合成一个对象;
  • 构造一个 DiffUtil.Callback 对象,实现 getOldListSize、getNewListSize、areItemsTheSame 和 areContentsTheSame 四个方法;
  • 在适配器的 onBindViewHolder 方法中,将 DiffResult 中的差异应用到视图中。

以下是完整代码示例:

---- ----- -------------------- ----- ----- --- --------- ----

----- ------------------------ --- -------- ----------- ------- --- -------- ----------- - ------------------- -

    -------- --- ----------------- --- -
        ------ ------------
    -

    -------- --- ----------------- --- -
        ------ ------------
    -

    -------- --- -------------------------------- ---- ---------------- ----- ------- -
        ------ ------------------------ -- ------------------------
    -

    -------- --- ----------------------------------- ---- ---------------- ----- ------- -
        ------ ------------------------ -- ------------------------
    -
-

----- -------------------- --- --------- ----------- - -------------------------------------- -

    -------- --- -------------------------- ---------- --------- ----- -------------- -
        --- ---- - ----------------------------------------------------------------- ------- ------
        ------ --------------------
    -

    -------- --- ------------------------ --------------- --------- ---- -
        --- ---- - -----------------------
        ----------------- - ----------
        ---------------------------------------------------------------
    -

    -------- --- --------------- --- -
        ------ -------------
    -

    --- --------------------- ----------- -
        --- ------- - ------------------- - ------ ---- -- ---------------------- ------ -
        --- ------- - ------------------- - ------ ---- -- ---------------------- ------ -
        --- ---------- - ------------------------------------------------- ----------
        -------- - --------
        ----------------------------------
    -
-

其中,ItemWithPosition 是一个包含 Item 和它在列表中位置的数据类。在适配器中,我们使用 updateItems 方法来更新数据,该方法首先将新旧数据列表转换为包含位置信息的 ItemWithPosition 列表,然后计算 DiffResult 并将它应用到适配器中。

实现拖拽排序

在某些应用中,我们需要实现拖拽排序的功能,即用户可以通过拖动列表条目来改变它们的位置。RecyclerView 提供了 ItemTouchHelper 类来帮助我们完成这个功能,它可以响应触摸事件,并管理相关的拖拽和移除操作。

使用 ItemTouchHelper 需要完成以下步骤:

  • 实现 ItemTouchHelper.Callback 类,并实现 onMove 和 onSwiped 两个方法;
  • 在适配器类中,定义一个 ItemTouchHelper 对象,并在 ViewHolder 构造函数中调用 ItemTouchHelper 的 attachToRecyclerView 方法将其绑定到 RecyclerView 上;
  • 在适配器的 onBindViewHolder 方法中,对被拖动的条目设置触摸事件,当用户拖动条目时,调用 ItemTouchHelper 的 startDrag 方法来开始拖动操作。

以下是完整代码示例:

----- -------------------- --- ------ ----------- - --------------------------------------- ---------------------- -

    ------- --- --------------- - ----------------------------------------------

    -------- --- -------------------------- ---------- --------- ----- -------------- -
        --- ---- - ----------------------------------------------------------------- ------- ------
        ------ --------------------
    -

    -------- --- ------------------------ --------------- --------- ---- -
        --- ---- - ---------------
        ----------------- - ----------
        ---------------------------------------------------------------

        ---------------------------------- - -- ----- --
            -- ------------------- -- ------------------------ -
                ---------------------------------
            -
            -----
        -
    -

    -------- --- --------------- --- -
        ------ ----------
    -

    -------- --- ------------------------ ---- ----------- ---- -
        -- ------------- - ----------- -
            --- -- -- ------------ ----- ----------- -
                ----------------------- -- - - --
            -
        - ---- -
            --- -- -- ------------ ------ ---------- - -- -
                ----------------------- -- - - --
            -
        -
        ----------------------------- -----------
    -

    -------- --- ----------------------- ---- -
        ----- - ------------------- - ------ - -- ----- -- -------- -
        ---------------------------
    -

    ---- -
        --------------------------------------------------
    -
-

--------- ---------------------- -
    --- ------------------------ ---- ----------- ----
    --- ----------------------- ----
-

----- ------------------------------- --- -------- ----------------------- - -------------------------- -

    -------- --- ------------------------------ ------------- ----------- ------------------------- --- -
        --- --------- - ------------------ -- --------------------
        --- ---------- - --------------------- -- -------------------
        ------ ---------------------------- -----------
    -

    -------- --- -------------------- ------------- ----------- ------------------------ ------- ------------------------- ------- -
        ---------------------------------------------- -----------------------
        ------ ----
    -

    -------- --- -------------------- ------------------------ ---------- ---- -
        -------------------------------------------------
    -
-

其中,ItemTouchHelperAdapter 接口定义了两个方法,用于在适配器中响应拖拽和移除操作。在适配器中,我们使用 itemTouchHelper 对象来处理拖拽操作,在渲染每个条目时,为它添加一个触摸事件,当用户手指按下时,通过调用 startDrag 方法来开始拖动操作,从而触发 onItemMove 方法。在 ItemTouchHelperCallback 中,我们可以设置支持拖拽和滑动的方向,以及实现对应操作的逻辑。

总结

RecyclerView 是 Material Design 中使用广泛的、高度定制的列表控件。通过使用 RecyclerView,我们可以更好地管理大量数据、提供更佳的用户体验、提高应用性能和可维护性。

在本文中,我们详细介绍了 RecyclerView 的基本使用和进阶技巧,包括使用 DiffUtil 进行列表更新、实现拖拽排序等高级功能。我们相信,通过学习和实践,您可以掌握 RecyclerView 的精髓,并在自己的项目中应用这些技术。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/6650dd1dd3423812e43ac9c3


猜你喜欢

  • Express.js 中使用 Connect-flash 实现 Flash 消息

    介绍 Flash 消息是指在应用程序中显示一条消息,然后在下一次请求时将其删除。例如,在用户成功登录后,显示一个"欢迎回来!"的消息,并在下一次请求时将其隐藏。 在 Express.js 应用程序中,...

    5 个月前
  • Angular 中如何使用 xhook 进行拦截 AJAX 请求 - 教程

    当我们在进行前端开发时,经常需要跟后端进行数据交互,而 AJAX 就是实现这种交互的主要方式之一。在实际开发中,我们有时候需要对 AJAX 请求进行拦截和修改,这时候就需要使用一些库来辅助我们实现这个...

    5 个月前
  • 如何使用 Jest 测试 Angular 应用程序的最佳实践

    在 Angular 应用程序中使用 Jest 进行单元测试是一个非常好的选择。 Jest 是一个很受欢迎的 JavaScript 测试库,它提供了一个简单的 API 和虚拟 DOM,使得编写和运行测试...

    5 个月前
  • 使用 Hapi.js 实现 OAuth2 授权流程的方案

    OAuth2 是一种用户授权的开放协议,可以让第三方的服务或应用程序以用户的身份访问另一个服务或应用程序的资源。OAuth2 协议包括授权流程、令牌交换和 API 调用等多个方面。

    5 个月前
  • 利用 MongoDB 进行数据统计和分析

    作为一名前端开发工程师,我们需要对用户的行为进行统计和分析,以便更好地理解用户需求和优化产品。MongoDB 是一个非关系型数据库,可以用来存储大量的数据并进行灵活的统计和分析。

    5 个月前
  • ngx-sse,基于 Nginx 的 SSE 服务

    简介 ngx-sse 是一款基于 Nginx 的 SSE(Server-Sent Events)服务,使用它可以实现基于 HTTP 的实时通信。它的特点是可以在不需要任何插件的情况下,在服务器和客户端...

    5 个月前
  • 使用 Cypress 的网络代理进行 HTTP 请求

    Cypress 是一款流行的前端自动化测试工具,它允许我们编写端到端测试来模拟用户在浏览器中与我们的网站交互,以确保网站的行为符合我们的预期。Cypress 还提供了其他功能,例如模拟不同的浏览器和设...

    5 个月前
  • 如何使用 TypeScript 定义 Vue 组件?

    在开发 Vue 应用的过程中,我们通常需要编写一些组件来实现特定的功能。Vue 组件可以帮助我们封装 HTML、CSS 和 JavaScript 代码以实现复用性和可维护性。

    5 个月前
  • 利用 Apollo Client 实现 GraphQL 数据预取优化

    在前端的开发中,数据预取是优化网站性能的重要策略之一。GraphQL 是一种用于 API 的查询语言,通过对数据的请求进行分组和预取,可以最大化减少不必要的数据请求,提高页面的加载速度。

    5 个月前
  • Angular 中如何实现光标自动聚焦 - 教程

    在 Angular 中实现光标自动聚焦是非常常见的需求,特别是在表单提交场景中。本篇文章将会详细地介绍如何在 Angular 中实现光标自动聚焦,包含代码示例和详细的步骤指导,让你轻松上手。

    5 个月前
  • Hapi.js Cookie 插件的使用详解

    Hapi.js 是一个用于编写 Web 应用程序的 Node.js 框架,它提供了一系列强大的功能和插件,其中包括 Cookie 插件。Hapi.js Cookie 插件提供了一种方便的方式,使开发者...

    5 个月前
  • Redis 使用过程中遇到”max number of clients reached” 怎么办?

    在使用 Redis 进行开发时,我们可能会遇到这样的错误提示:“max number of clients reached”。这个错误提示的意思是 Redis 已经达到了最大客户端连接数,无法再接受新...

    5 个月前
  • 实战 Koa2 + Mongodb + JWT + RESTful API

    前言 前端的技术栈在不断地更新和变化,现如今,可以说是前端类的技术栈也越来越丰富。出于对于学习前端技术的热情,我在这里将介绍一种基于 Koa2 + MongoDB + JWT + RESTful AP...

    5 个月前
  • ESLint and Prettier 配合使得代码规范又美观可看

    ESLint and Prettier 配合使得代码规范又美观可看 前言 在前端开发中,代码的规范问题无疑是非常重要的。一份代码的质量很大程度上决定了用户的体验以及代码的可维护性。

    5 个月前
  • Express.js 中使用 Passport.js 实现 OAuth 认证

    在 Web 开发中,用户认证和授权是一项必不可少的功能。随着 Web 应用规模的增大和用户量的增长,传统的本地认证方式已经难以满足需求。 OAuth2.0 是一个授权框架,它使得用户可以授权第三方应用...

    5 个月前
  • 如何在 Enzyme 中使用 “mount” 方法渲染组件?

    Enzyme 是一个流行的 React 测试库,可以帮助开发者在生成器中测试 React 组件。其中,mount() 方法可以渲染一个 React 组件并返回相应的 enzyme 风格的组件包装器,以...

    5 个月前
  • 如何在 Fastify 框架中使用 Sentry 日志系统

    Sentry 是一款优秀的日志系统,为我们提供了便捷的日志记录、错误捕捉和实时反馈等功能。在前端开发中,我们需要记录一些用户行为、应用状态和错误信息,为了更好地保障产品质量和用户体验,我们可以使用 S...

    5 个月前
  • 一个基于 RxJS 实现的轮子:rxjs-hooks

    RxJS 是一个非常强大的库,它提供了许多工具和方法来处理异步事件流。在前端开发中,我们经常需要处理各种异步事件,例如 user interaction,网络请求和定时器等等。

    5 个月前
  • 搭建 Deno 应用的 web 框架:oak 详解

    随着 Deno 的逐渐流行,前端开发领域也开始出现许多基于 Deno 的框架和工具。其中,oak 是一款轻量级、灵活、可扩展的 web 框架,它能够帮助我们快速搭建 Deno 应用。

    5 个月前
  • ES11 中优化 async/await 的 try...catch 语法

    ES11 中优化 async/await 的 try...catch 语法 在 JavaScript 中,async/await 是在处理异步函数时最常用的方法之一。

    5 个月前

相关推荐

    暂无文章