文章欢迎转载,转载请注明出处:文章首发于【Karen Chia の 程序人生】RecyclerView系列 - RecyclerView的基本使用
按照惯例,先上效果图 效果图不是我想要的效果,怎么办?
查看关于 RecyclerView 系列的其它文章,总有你想要的效果 ↓↓↓
KarenChia 的 RecyclerView 系列文章 RecyclerView系列 - RecyclerView的基本使用
RecyclerView系列 - 如何优雅的实现分割线
前言 RecyclerView 在本文发布之前,已经出来很久了,之前也有很多关于 RecyclerView 的优秀文章,那我为什么还要在这里写下本文呢,实不相瞒,我是 ListView 的忠实粉,之前很少使用到 RecyclerView,最近发现了不少关于 RecyclerView 的优秀框架,于是开始使用 RecyclerView,在使用第三方优秀框架的同时,也需要了解框架背后对组件进行的处理及封装,便于后期对项目维护。
为什么选择 RecyclerView? 相对于 ListView、GridView 这类滑动列表组件来说,RecyclerView 具有:
使用更加灵活 1 通过设置布局管理器,可轻松实现组件列表垂直滑动或水平滑动效果 2 给列表的 item 项设置【增加或删除】动画 3 当列表组件滑动到顶端或底部时,带有波纹效果,更显列表立体感
代码高度解耦 代码高幅度降低了耦合度,维护起来非常方便
拓展方便 1 轻松实现 ListView 及 Gridview 组件的相关列表效果,学会 RecyclerView,相当于学会了 ListView + Gridview 2 难得一见的【瀑布流】列表滑动效果
RecyclerView 不是万能的,存在以下不足:
不像 ListView那样,它没有分割线的设置方法
没有实现 item 的相关点击事件
但是,重点来了:
也正是由于 RecyclerView 存在的这些缺点,我们不就可以根据自己的需求去定义嘛,怎么开心怎么玩!!!
下面开始进入我们今天的主题 ↓↓↓
1 添加依赖 在 module(一般都是在 app 下) 的 build.gradle 文件下添加组件依赖:
implementation 'androidx.recyclerview:recyclerview:1.0.0'
注意:由于使用的 Android Studio 版本不同,依赖语句也有所不同,我这里使用的 AS 版本是 V3.4.1
2 在布局文件中使用 RecyclerView <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/app_bg" android:orientation="vertical"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rvTest" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
3 为 RecycleView 设置布局管理器 LinearLayoutManager 这里列表默认是垂直滑动的
rvTest.setLayoutManager(new LinearLayoutManager(this));
不要问我为什么,问就【看源码】,看 LinearLayoutManager 构造器源码:
/** * Creates a vertical LinearLayoutManager * * @param context Current context, will be used to access resources. */ public LinearLayoutManager(Context context) { this(context, RecyclerView.DEFAULT_ORIENTATION, false); }
关于 DEFAULT_ORIENTATION 的定义如下:
static final int DEFAULT_ORIENTATION = VERTICAL;
关于 VERTICAL 的定义如下:
public static final int VERTICAL = LinearLayout.VERTICAL;
源码中使用的属性还是线性布局 LinearLayout 的垂直属性
那么问题来了,我要让 RecyclerView 水平滑动怎么办?
3.1 设置 RecyclerView 列表水平滑动 LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this); mLinearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); rvTest.setLayoutManager(mLinearLayoutManager);
4 设置 item 增加和删除时的动画效果 rvTest.setItemAnimator(new DefaultItemAnimator());
这里设置的是 RecyclerView 默认的动画效果
5 设置适配器 mRecyclerViewTestAdapter = new RecyclerViewTestAdapter(this, testData); rvTest.setAdapter(mRecyclerViewTestAdapter);
RecyclerView 的适配器继承至 RecyclerView.Adapter < VH extends ViewHolder >,泛型类型为ViewHolder。
RecyclerView 对 ViewHolder 进行了封装,使得我们使用起来更加的方便,自定义的 ViewHolder 只需继承 RecyclerView.ViewHolder 即可
package com.karenchia.andprimarylp.adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.karenchia.andprimarylp.R; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; /** * RecyclerView 测试数据适配器 * <p> * Created by KarenChia on 2019/9/4. */ public class RecyclerViewTestAdapter extends RecyclerView.Adapter<RecyclerViewTestAdapter.RecyclerViewTestViewHolder> { /** * 上下文对象 */ private Context mContext; /** * 测试数据 */ private List<String> testDataList; /** * 函数构造器 * * @param mContext 上下文对象 * @param testDataList 测试数据 */ public RecyclerViewTestAdapter(Context mContext, List<String> testDataList) { this.mContext = mContext; this.testDataList = testDataList; } /** * 加载 item 的布局文件 */ @NonNull @Override public RecyclerViewTestViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { return new RecyclerViewTestViewHolder( LayoutInflater.from(mContext).inflate(R.layout.item_recycler_view_test, parent, false)); } /** * 将数据与 item 视图进行绑定 */ @Override public void onBindViewHolder(@NonNull RecyclerViewTestViewHolder holder, int position) { holder.tvData.setText(testDataList.get(position)); } @Override public int getItemCount() { return testDataList == null ? 0 : testDataList.size(); } /** * RecycleView 中 ViewHolder 的定义方式 */ public class RecyclerViewTestViewHolder extends RecyclerView.ViewHolder { @BindView(R.id.tvData) TextView tvData; public RecyclerViewTestViewHolder(@NonNull View itemView) { super(itemView); ButterKnife.bind(this, itemView); } } }
列表 item 布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="10dp"> <TextView android:id="@+id/tvData" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/black" /> </LinearLayout>
至此,RecyclerView 的基本用法结束。
6 相关类的代码 这里贴一下相关类的代码实现
项目使用的是 MVP 模式,别问我为什么要使用 MVP 模式,问就请看这里:https://blog.csdn.net/ZhaiKun68/article/details/100033584#1_AndroidMVP_3
6.1 RecyclerViewDemoContract 类 package com.karenchia.andprimarylp.ui.contract; import java.util.List; /** * MVP 模式接口抽取 * <p> * Created by KarenChia on 2019/9/4. */ public interface RecyclerViewDemoContract { interface Model { /** * 加载测试数据 * * @return 测试数据 */ List<String> testData(); } interface View { /** * 显示测试数据列表 * * @param testData 测试数据 */ void showTestData(List<String> testData); } interface Presenter { /** * 获取测试数据 */ void getTestData(); } }
6.2 RecyclerViewDemoModel 类 package com.karenchia.andprimarylp.ui.model; import com.karenchia.andprimarylp.ui.contract.RecyclerViewDemoContract; import java.util.ArrayList; import java.util.List; /** * model 层数据逻辑处理 * <p> * Created by KarenChia on 2019/9/4. */ public class RecyclerViewDemoModel implements RecyclerViewDemoContract.Model { /** * 加载测试数据 * * @return 测试数据 */ @Override public List<String> testData() { List<String> testData = new ArrayList<>(); for (int i = 0; i < 20; i++) { testData.add("我是 Karen Chia " + i); } return testData; } }
6.3 RecyclerViewDemoActivity 类 package com.karenchia.andprimarylp.ui.activity.newfeature; import android.content.Context; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.DefaultItemAnimator; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.karenchia.andprimarylp.R; import com.karenchia.andprimarylp.adapter.RecyclerViewTestAdapter; import com.karenchia.andprimarylp.ui.contract.RecyclerViewDemoContract; import com.karenchia.andprimarylp.ui.presenter.RecyclerViewDemoPresenter; import com.socks.library.KLog; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; /** * RecyclerView 演示类 view 层逻辑处理 * <p> * Created by KarenChia on 2019/9/3. */ public class RecyclerViewDemoActivity extends AppCompatActivity implements RecyclerViewDemoContract.View { /** * view层与model层交互的桥梁 */ private RecyclerViewDemoContract.Presenter mPresenter; /** * RecyclerView 组件 */ @BindView(R.id.rvTest) RecyclerView rvTest; /** * RecyclerView 的数据适配器 */ private RecyclerViewTestAdapter mRecyclerViewTestAdapter; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycler_view_demo); ButterKnife.bind(this); mPresenter = new RecyclerViewDemoPresenter(this); initData(); initView(); } private void initData() { mPresenter.getTestData(); } /** * 组件初始化 */ private void initView() { //为 RecycleView 设置布局管理器 rvTest.setLayoutManager(new LinearLayoutManager(this)); //LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this); //mLinearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); //rvTest.setLayoutManager(mLinearLayoutManager); //设置 item 增加和删除时的动画效果 rvTest.setItemAnimator(new DefaultItemAnimator()); } /** * 显示测试数据列表 * * @param testData 测试数据 */ @Override public void showTestData(List<String> testData) { //设置适配器 mRecyclerViewTestAdapter = new RecyclerViewTestAdapter(this, testData); rvTest.setAdapter(mRecyclerViewTestAdapter); } }
6.4 RecyclerViewDemoPresenter 类 package com.karenchia.andprimarylp.ui.presenter; import com.karenchia.andprimarylp.ui.contract.RecyclerViewDemoContract; import com.karenchia.andprimarylp.ui.model.RecyclerViewDemoModel; /** * model层 与 View层 通信的桥梁 * <p> * Created by KarenChia on 2019/9/4. */ public class RecyclerViewDemoPresenter implements RecyclerViewDemoContract.Presenter { /** * model层数据逻辑处理 */ private RecyclerViewDemoContract.Model mModel; /** * view层交互逻辑处理 */ private RecyclerViewDemoContract.View mView; public RecyclerViewDemoPresenter(RecyclerViewDemoContract.View mView) { mModel = new RecyclerViewDemoModel(); this.mView = mView; } /** * 获取测试数据 */ @Override public void getTestData() { mView.showTestData(mModel.testData()); } }