Android Material Design 列表与卡片实战:RecyclerView 与 CardView 完整使用指南

发布时间:2026/10/7 1:50:06
Android Material Design 列表与卡片实战:RecyclerView 与 CardView 完整使用指南 文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载本篇指南基于 Android 官方培训课程中文版本仓库的「创建 Lists 与 Cards」章节系统讲解 Material Design 应用中最常用的两大列表型组件RecyclerView与CardView。你将掌握 RecyclerView 的 LayoutManager Adapter 架构、视图回收机制、内建布局管理器与动画体系以及 CardView 的阴影、圆角定制方法并了解如何在 Android 5.0API level 21以下版本中通过 v7 Support Library 保持兼容。文中所有代码均来自本仓库 material/lists-cards.md并辅以 material/compatibility.md 与 tv/playback/card.md 等章节的源码级佐证。图1.RecyclerView组件图片来源material/RecyclerView.png一、RecyclerView更高级、更灵活的列表容器RecyclerView是比ListView更高级、伸缩性更强的列表组件。它是一个显示大量数据的容器核心设计目标是通过维护有限数量的 View实现滚动时的高效渲染。当你的数据集会在运行过程中根据用户行为或网络事件动态更新时应当优先选择RecyclerView而不是ListView。RecyclerView 通过以下两种方式简化显示流程并高效处理大量数据使用 LayoutManager 来定位元素元素如何排列线性、网格、瀑布流完全由 LayoutManager 决定列表的视觉形态与数据绑定逻辑彻底解耦为常用操作定义默认动画例如添加或移除元素时RecyclerView 默认会播放过渡动画无需你手写notifyDataSetChanged()之外的特效代码。同时你也可以为 RecyclerView自定义 LayoutManager 和动画这一点将在后文展开。要使用 RecyclerView 组件你需要同时定义两样东西Adapter负责把数据集中的每一项转换为可视的 View 层级LayoutManager负责把 Adapter 产出的 View 放到 RecyclerView 中并决定何时回收不可见的 View。创建 Adapter 需要继承RecyclerView.Adapter类实现类的具体细节取决于你的数据集结构和视图类型第五节会给出完整示例。二、LayoutManager三种内建布局管理器LayoutManager负责把元素视图安放到RecyclerView中并决定何时重用回收不可见的元素视图。当需要回收视图时LayoutManager 会让 Adapter 用新的元素内容替换视图内的旧内容。这种视图回收机制是 RecyclerView 高性能的关键它避免了创建不必要的 View 对象也避免了执行昂贵的findViewById()查找——这正是复用 ViewHolder 的意义所在。RecyclerView 提供以下三种内建的 LayoutManagerLayoutManager适用场景LinearLayoutManager显示横向或纵向滚动的列表最常用对应传统 ListViewGridLayoutManager显示方格网格元素支持指定每行列数StaggeredGridLayoutManager在 staggered交错瀑布流方格中显示元素适合图片瀑布流等不等高内容图2. LayoutManager 决定元素在列表中的位置与回收时机图片来源material/list_mail.png自定义 LayoutManager如果三种内建布局管理器都无法满足需求例如需要圆形排布、时间轴等特殊形态可以继承RecyclerView.LayoutManager类覆写测量、布局与回收逻辑实现完全自定义的排列方式。三、动画默认启用的增删动画与自定义 ItemAnimator添加和删除元素的动画在 RecyclerView 中默认启用这意味着当你调用 Adapter 的增删方法并通知数据集变化时元素会以平滑的过渡动画呈现而不需要额外配置。要自定义动画你需要继承RecyclerView.ItemAnimator类实现自己的动画逻辑调用RecyclerView.setItemAnimator()方法将自定义动画应用到 RecyclerView 实例上。动画体系让列表的增删操作拥有 Material Design 要求的视觉连续性是「信息变化有反馈」这一设计原则在列表组件中的落地。四、实战第一步在 Layout 中添加 RecyclerView 并接入 Activity以下 XML 展示了如何把一个带常用属性的 RecyclerView 加入布局!-- A RecyclerView with some commonly used attributes -- android.support.v7.widget.RecyclerView android:idid/my_recycler_view android:scrollbarsvertical android:layout_widthmatch_parent android:layout_heightmatch_parent/注意这里使用的是 v7 Support Library 中的android.support.v7.widget.RecyclerView历史包名。在现代工程中对应的 AndroidX 版本为androidx.recyclerview.widget.RecyclerView使用方式完全一致。把 RecyclerView 组件加入 Layout 之后需要在 Activity 中获取 RecyclerView 对象、把它连接到 LayoutManager并附上 Adapter 用于数据展示public class MyActivity extends Activity { private RecyclerView mRecyclerView; private RecyclerView.Adapter mAdapter; private RecyclerView.LayoutManager mLayoutManager; Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_activity); mRecyclerView (RecyclerView) findViewById(R.id.my_recycler_view); // use this setting to improve performance if you know that changes // in content do not change the layout size of the RecyclerView mRecyclerView.setHasFixedSize(true); // use a linear layout manager mLayoutManager new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); // specify an adapter (see also next example) mAdapter new MyAdapter(myDataset); mRecyclerView.setAdapter(mAdapter); } ... }这段代码中有几个值得注意的实践细节setHasFixedSize(true)如果你明确知道数据集内容的变化不会改变 RecyclerView 的布局尺寸例如列表高度始终铺满父容器设置该标记可显著提升性能——它让 RecyclerView 跳过对 item 尺寸变化的测量new LinearLayoutManager(this)默认构造即纵向列表如需横向滚动调用setOrientation(LinearLayoutManager.HORIZONTAL)即可初始化顺序先设 LayoutManager再setAdapter()这是官方推荐的标准接线流程。五、实战第二步完整实现 Adapter 与 ViewHolderAdapter 承担三项职责获取数据集元素、创建元素的视图、以及用新元素内容替换不可见视图中的旧内容。以下代码展示了一个简单实现——数据集是字符串数组每个数据元素用 TextView 显示public class MyAdapter extends RecyclerView.AdapterMyAdapter.ViewHolder { private String[] mDataset; // Provide a reference to the views for each data item // Complex data items may need more than one view per item, and // you provide access to all the views for a data item in a view holder public static class ViewHolder extends RecyclerView.ViewHolder { // each data item is just a string in this case public TextView mTextView; public ViewHolder(TextView v) { super(v); mTextView v; } } // Provide a suitable constructor (depends on the kind of dataset) public MyAdapter(String[] myDataset) { mDataset myDataset; } // Create new views (invoked by the layout manager) Override public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // create a new view View v LayoutInflater.from(parent.getContext()) .inflate(R.layout.my_text_view, parent, false); // set the views size, margins, paddings and layout parameters ... ViewHolder vh new ViewHolder(v); return vh; } // Replace the contents of a view (invoked by the layout manager) Override public void onBindViewHolder(ViewHolder holder, int position) { // - get element from your dataset at this position // - replace the contents of the view with that element holder.mTextView.setText(mDataset[position]); } // Return the size of your dataset (invoked by the layout manager) Override public int getItemCount() { return mDataset.length; } }理解这套回调的关键在于它们由 LayoutManager 驱动而非手动调用onCreateViewHolder(parent, viewType)只在需要创建新视图时被 LayoutManager 调用。这里通过LayoutInflater从R.layout.my_text_view布局创建 View并包裹进 ViewHolderinflate(..., parent, false)中false表示暂不立即附加到父容器onBindViewHolder(holder, position)LayoutManager 在复用旧视图时调用用position处的数据集元素替换视图内容。由于视图已存在这里不需要重新 inflate 或 findViewByIdgetItemCount()返回数据集大小LayoutManager 据此决定要显示多少条目。ViewHolder 模式的精髓View 一旦创建便被缓存进 ViewHolder滚动出屏幕的 item 会被回收复用配合第二节所述的 LayoutManager 回收机制彻底避免高频findViewById()带来的性能开销。如果你的 item 有多种类型如带头部/正文/底部可覆写getItemViewType()区分 viewType在onCreateViewHolder中分别创建对应布局。六、CardViewMaterial Design 卡片图3. 使用 CardView 呈现内容卡片的示例图片来源material/card_travel.pngCardView继承自FrameLayout类它可以在卡片中显示信息并在不同平台上保持统一的视觉风格。CardView 组件支持设定阴影elevation和圆角corner radius这正是 Material Design 卡片式布局的两大核心外观要素。阴影Elevation与版本差异要创建一个带阴影的卡片使用card_view:cardElevation属性在 Android 5.0API level 21及以上的系统中CardView 使用真实高度值elevation以及动态阴影效果——阴影会随 elevation 值变化实时渲染在 5.0 以下的版本中CardView 采用编程实现阴影的备选方案详见第七节的兼容性限制。三个自定义属性使用以下属性来自定义 CardView属性 / 方法设置方式作用card_view:cardCornerRadiusLayout XML设置卡片圆角半径CardView.setRadius()Java 代码在代码中动态设置圆角card_view:cardBackgroundColorLayout XML设置卡片背景颜色完整 XML 示例以下代码展示了如何在 Layout 中添加一个包含 TextView 的 CardViewLinearLayout xmlns:androidhttp://schemas.android.com/apk/res/android xmlns:toolshttp://schemas.android.com/tools xmlns:card_viewhttp://schemas.android.com/apk/res-auto ... !-- A CardView that contains a TextView -- android.support.v7.widget.CardView xmlns:card_viewhttp://schemas.android.com/apk/res-auto android:idid/card_view android:layout_gravitycenter android:layout_width200dp android:layout_height200dp card_view:cardCornerRadius4dp TextView android:idid/info_text android:layout_widthmatch_parent android:layout_heightmatch_parent / /android.support.v7.widget.CardView /LinearLayout需要注意的关键点使用card_view:前缀的自定义属性时必须声明命名空间xmlns:card_viewhttp://schemas.android.com/apk/res-auto且cardElevation、cardCornerRadius等均需声明为dp单位CardView 继承自 FrameLayout因此其内部可以像 FrameLayout 一样放置任意 View 层级CardView 负责提供统一的卡片外观圆角 阴影 背景色如需代码动态调整圆角调用cardView.setRadius(4f)即可效果等同于card_view:cardCornerRadius4dp。七、添加依赖与旧版本兼容RecyclerView 和 CardView 都属于v7 Support Library的一部分。要使用这两个组件需要在 Gradle 依赖中添加两个模块dependencies { ... compile com.android.support:cardview-v7:21.0. compile com.android.support:recyclerview-v7:21.0. }该依赖写法对应 Android 官方培训课程编写时代Support Library 21.x的历史格式。现代 Android 工程已全面迁移至 AndroidX等价依赖为androidx.cardview:cardview与androidx.recyclerview:recyclerview旧工程升级时通常由 Android Studio 的 Migrate to AndroidX 自动完成转换。v7 Support Library 提供的 Material 特性根据本仓库 material/compatibility.mdv7 Support Librariesr21 及更高版本包含了以下 Material Design 特性应用Theme.AppCompat主题时会为系统控件提供 Material Design 样式Theme.AppCompat主题包含调色板主体属性colorPrimary、colorPrimaryDark、colorAccentRecyclerView组件用于显示数据集CardView组件用于创建卡片Palette类用于从图片提取主色调。CardView 在旧版本上的两个限制通过 v7 Support LibraryRecyclerView 和 CardView 可以支持 Android 5.0 之前的旧版本但有以下限制CardView 需要编程实现阴影和额外的 padding旧版本无法使用 5.0 的原生动态阴影阴影与内容间距需要由 Support Library 的兼容实现计算因此会引入额外的 paddingCardView 不能裁剪与卡片本身有重合部分的子视图受旧版本兼容机制所限clipToPadding等裁剪行为在低版本上无法完全支持。如果需要进一步为不同系统版本提供备选主题与布局可参考 material/compatibility.md 中的三种方案在res/values/styles.xml与res/values-v21/styles.xml中定义同名但不同父主题的备选 Style在res/layout/与res/layout-v21/中提供备选 Layout并在运行时通过Build.VERSION.SDK_INT Build.VERSION_CODES.LOLLIPOP判断是否调用 5.0 专属 API。八、仓库中的更多应用Android TV 卡片实现本仓库的 TV 模块 tv/playback/card.md 展示了卡片思想在 Android TVLeanback 库中的落地电视应用使用 v17 leanback 库的BaseCardView及其子类ImageCardView展示媒体项目元数据通过自定义Presenter的onCreateViewHolder()创建卡片视图、setSelected()处理选中态背景色变化并调用setFocusable(true)与setFocusableInTouchMode(true)支持 D-pad 遥控焦点控制。这说明「列表 卡片」并非手机端专利RecyclerView/CardView 是通用容器方案而 Leanback 的BaseCardView/Presenter是其在大屏交互场景下的 TV 特化形态。二者共享同样的核心思想——视图回收复用、Presenter/Adapter 负责数据到视图的绑定。阅读该章节可以帮助你理解同一个数据模型如何在手机RecyclerView CardView与 TVImageCardView Presenter两端复用。总结通过本篇指南你已经掌握了 Material Design 列表与卡片的完整技术栈RecyclerView以 LayoutManager 定位元素、以 Adapter 绑定数据、以 ViewHolder 机制回收视图是比 ListView 更高效、更灵活的容器三种内建 LayoutManagerLinearLayoutManager线性、GridLayoutManager网格、StaggeredGridLayoutManager瀑布流必要时可继承RecyclerView.LayoutManager自定义动画体系增删元素动画默认开启可继承RecyclerView.ItemAnimator并用setItemAnimator()自定义CardView继承自 FrameLayout通过cardElevation获得阴影、通过cardCornerRadius/setRadius()设置圆角、通过cardBackgroundColor设置背景色兼容方案借助cardview-v7与recyclerview-v7两个 Support Library 模块在 Android 5.0 以下版本中也可使用但需留意 CardView 编程阴影与无法裁剪重叠子视图的限制。更进一步的 Material Design 实践主题、阴影与 Clipping、矢量 Drawable、自定义动画、Palette 取色等可继续研读本仓库 material/index.md 中的其他课程章节。赞分享文档教程移动开发【免费下载链接】android-training-course-in-chineseAndroid官方培训课程中文版项目地址https://gitcode.com/gh_mirrors/an/android-training-course-in-chinese点击查看免费下载相关推荐如何用跨平台资源下载工具轻松捕获网络资源完整指南如何用跨平台资源下载工具轻松捕获网络资源完整指南 还在为无法保存喜欢的在线视频而烦恼吗想要下载无水印内容却找不到合适的工具今天我要介绍的跨平台资源下载工具桌面应用网络音视频Android Material Design组件集成CardView、RecyclerView、ViewPager2最佳组合方案 Android Material Design组件集成CardView、RecyclerView、ViewPager2最佳组合方案 想要打造现代化、流畅示例工程彻底解决Android列表卡顿RecyclerView优化实战指南彻底解决Android列表卡顿RecyclerView优化实战指南 你是否遇到过这样的情况精心设计的App在快速滑动列表时出现明显卡顿用户投诉体验差知识库移动开发教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考