文章目录
背景
RecyclerView 控件和 ListView 控件类似,用来在一个页面展示大量数据用的。但是RecyclerView 的使用更加的灵活和方便。可以支持
- LinerLayoutManager:以垂直或者水平列表方式展示Item、
- GridLayoutManager:以网格方式展示Item、
- StaggeredGridLayoutManager:以瀑布流方式展示Item。
而且自带控件缓存的实现,非常的棒!所以项目开发中涉及到展示大量数据的时候, RecyclerView 控件绝对是你独一无二的选择。但是实际开发中需要对其进行相关功能的扩展,这里记录一下,方便自己日后温习并加深理解。
RecyclerView 概述
官方介绍,RecyclerView用于在有限的窗口展现大量的数据,其实早已经有了类似的控件,如ListView、GridView,那么相比它们,RecyclerView有什么样优势呢?
RecyclerView标准化了ViewHolder,而且异常的灵活,可以轻松实现ListView实现不了的样式和功能,通过布局管理器LayoutManager可控制Item的布局方式,通过设置Item操作动画自定义Item添加和删除的动画,通过设置Item之间的间隔样式,自定义间隔。
RecyclerView 的使用
添加依赖
implementation 'com.android.support:recyclerview-v7:27.1.1'
依赖添加完,同步gradle后就可以在xml布局文件中引用 RecyclerView 控件了。
控件引用
在xml文件中引用控件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:padding="10dp"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_demo"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
图示如下:
itemView 布局的创建
recyclerView 展示的数据,是由很多的item所组成的,所以我们需要创建一个itemView的xml布局文件,这里我在布局中只简单的创建了一个TextView来作展示,recyclerview_item_demo.xml 如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:background="@drawable/item_selector"
android:textSize="16sp"
android:id="@+id/tv_content"
android:textColor="@android:color/black"
android:text="demo"
android:padding="10dp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
图示如下:
继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
这里我们自定义MyRecyclerViewAdapter 继承 RecyclerView.Adapter并重写相关方法,MyRecyclerViewAdapter 类如下:
// 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{
private List<String> listData;
private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度
public MyRecyclerViewAdapter(List<String> listTemp) {
this.listData = listTemp;
// getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
}
/**
* 随机高度设置
* @param length item的个数
*/
public void getRandomHeight(int length){
heightList = new ArrayList<>();
for (int i = 0;i < length;i++){
int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
heightList.add(randomH);
}
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// 使用布局泵构建itemView的布局
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
// 创建MyViewHolder对象
MyViewHolder holder = new MyViewHolder(view);
// 返回MyViewHolder对象
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
// 给瀑布流效果的item设置随机高度
// ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
// params.height = heightList.get(position);
// holder.tv_content.setLayoutParams(params);
String content = listData.get(position);// 获取数据
holder.tv_content.setText(content);// 给item设置数据
}
@Override
public int getItemCount() {
return listData.size();// 返回item的个数
}
/**
* 创建MyViewHolder继承RecyclerView.ViewHolder
* 在内部方法MyViewHolder中缓存itemView中的控件
*/
class MyViewHolder extends RecyclerView.ViewHolder{
TextView tv_content;// itemView中的 TextView 控件
public MyViewHolder(View itemView) {
super(itemView);
// 缓存控件
tv_content = itemView.findViewById(R.id.tv_content);
}
}
}
上面的代码中有几行代码和方法我将其注释了,后面展示瀑布流效果的时候在将这些注释的代码放出来吧!这里先实现线性布局的效果。
到这里我们可以看到RecyclerViewAdapter的内部有自己的控件缓存实现,而不需要我们再像以前一样自己写代码去实现缓存控件的功能了。这也算是我喜欢用 RecyclerView 控件的原因之一吧!请原谅我的喜新厌旧,不过我是对技术说的!
MainActivity 中的主代码实现
适配器写好后,我们就可以获取 recyclerView 控件,并给其设置 adapter 即可。MainActivity 类代码如下:
package com.example.administrator.recyclerviewdemo;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends Activity{
@BindView(R.id.rv_demo)RecyclerView rv_demo;// RecyclerView控件
private List<String> list = new ArrayList<>();
private MyRecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initData();// 初始化模拟数据
}
/**
* 初始化数据
*/
private void initData() {
for (int i = 0;i < 40;i++){
list.add("demo item" + (i+1));
}
show();// 使用 RecyclerView 展示数据
}
/**
* 使用recyclerView展示数据
*/
private void show() {
// 第一步:创建 MyRecyclerViewAdapter
adapter = new MyRecyclerViewAdapter(list);
// 第二步:设置布局管理器,控制布局效果
// 线性垂直布局
rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));
// 线性水平布局
// rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));
// 网格布局
// rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));
// 瀑布流布局
// rv_demo.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
// 第三步:设置adapter
rv_demo.setAdapter(adapter);
rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果
}
// 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{
private List<String> listData;
private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度
private OnItemClickListener onItemClickListener;
public MyRecyclerViewAdapter(List<String> listTemp) {
this.listData = listTemp;
// getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
}
/**
* 随机高度设置
* @param length item的个数
*/
public void getRandomHeight(int length){
heightList = new ArrayList<>();
for (int i = 0;i < length;i++){
int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
heightList.add(randomH);
}
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// 使用布局泵构建itemView的布局
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
// 创建MyViewHolder对象
MyViewHolder holder = new MyViewHolder(view);
// 返回MyViewHolder对象
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
// 给瀑布流效果的item设置随机高度
// ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
// params.height = heightList.get(position);
// holder.tv_content.setLayoutParams(params);
String content = listData.get(position);// 获取数据
holder.tv_content.setText(content);// 给item设置数据
}
@Override
public int getItemCount() {
return listData.size();// 返回item的个数
}
/**
* 创建MyViewHolder继承RecyclerView.ViewHolder
* 在内部方法MyViewHolder中缓存itemView中的控件
*/
class MyViewHolder extends RecyclerView.ViewHolder{
TextView tv_content;// itemView中的 TextView 控件
public MyViewHolder(View itemView) {
super(itemView);
// 缓存控件
tv_content = itemView.findViewById(R.id.tv_content);
}
}
}
}
简单的说一下我的实现思路:
- 首先获取 recyclerView 控件,
- 初始化数据,然后创建 MyRecyclerViewAdapter ,
- 设置item 呈现的布局效果(线性、网格和瀑布流三种),
- 设置adapter,当然可以加上默认的动画。
我们现在运行一下看看效果:
成功的用 recyclerView 控件展示了数据(这里是线性布局垂直展示效果),基本的实现就是上面的几个步骤,下面我们来看看其他布局的效果。
线性布局水平展示效果
将对应注释的代码放开后,show() 方法的代码如下:
/**
* 使用recyclerView展示数据
*/
private void show() {
// 第一步:创建 MyRecyclerViewAdapter
adapter = new MyRecyclerViewAdapter(list);
// 第二步:设置布局管理器,控制布局效果
// 线性垂直布局
// rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));
// 线性水平布局
rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));
// 网格布局
// rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));
// 瀑布流布局
// rv_demo.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
// 第三步:设置adapter
rv_demo.setAdapter(adapter);
rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果
}
效果图示如下:
这里可以看到可以实现了线性布局的水平滑动效果。
网格布局效果实现
将对应注释的代码放开后,show() 方法的代码如下:
/**
* 使用recyclerView展示数据
*/
private void show() {
// 第一步:创建 MyRecyclerViewAdapter
adapter = new MyRecyclerViewAdapter(list);
// 第二步:设置布局管理器,控制布局效果
// 线性垂直布局
// rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));
// 线性水平布局
// rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));
// 网格布局
rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));
// 瀑布流布局
// rv_demo.setLayoutManager(new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
// 第三步:设置adapter
rv_demo.setAdapter(adapter);
rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果
}
上面代码中网格布局设置为了3列,效果展示如下:
瀑布流效果实现
这里除了 show() 方法需要放开对应注释后,还要在MyRecyclerViewAdapter 中将随机高度设置这部分代码的注释也放开,所以代码如下:
package com.example.administrator.recyclerviewdemo;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends Activity{
@BindView(R.id.rv_demo)RecyclerView rv_demo;// RecyclerView控件
private List<String> list = new ArrayList<>();
private MyRecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initData();// 初始化模拟数据
}
/**
* 初始化数据
*/
private void initData() {
for (int i = 0;i < 40;i++){
list.add("demo item" + (i+1));
}
show();// 使用 RecyclerView 展示数据
}
/**
* 使用recyclerView展示数据
*/
private void show() {
// 第一步:创建 MyRecyclerViewAdapter
adapter = new MyRecyclerViewAdapter(list);
// 第二步:设置布局管理器,控制布局效果
// 线性垂直布局
// rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));
// 线性水平布局
// rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));
// 网格布局
// rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));
// 瀑布流布局
rv_demo.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
// 第三步:设置adapter
rv_demo.setAdapter(adapter);
rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果
}
// 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{
private List<String> listData;
private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度
private OnItemClickListener onItemClickListener;
public MyRecyclerViewAdapter(List<String> listTemp) {
this.listData = listTemp;
getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
}
/**
* 随机高度设置
* @param length item的个数
*/
public void getRandomHeight(int length){
heightList = new ArrayList<>();
for (int i = 0;i < length;i++){
int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
heightList.add(randomH);
}
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// 使用布局泵构建itemView的布局
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
// 创建MyViewHolder对象
MyViewHolder holder = new MyViewHolder(view);
// 返回MyViewHolder对象
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
// 给瀑布流效果的item设置随机高度
ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
params.height = heightList.get(position);
holder.tv_content.setLayoutParams(params);
String content = listData.get(position);// 获取数据
holder.tv_content.setText(content);// 给item设置数据
}
@Override
public int getItemCount() {
return listData.size();// 返回item的个数
}
/**
* 创建MyViewHolder继承RecyclerView.ViewHolder
* 在内部方法MyViewHolder中缓存itemView中的控件
*/
class MyViewHolder extends RecyclerView.ViewHolder{
TextView tv_content;// itemView中的 TextView 控件
public MyViewHolder(View itemView) {
super(itemView);
// 缓存控件
tv_content = itemView.findViewById(R.id.tv_content);
}
}
}
}
同时需要将itemView的xml布局总根布局的固定高度设置为自适应(即wrap_content),如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:background="@drawable/item_selector"
android:textSize="16sp"
android:id="@+id/tv_content"
android:textColor="@android:color/black"
android:text="demo"
android:padding="10dp"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
运行一下,我们看看展示效果:
到这里瀑布流效果也实现了。
可以看到recyclerView 可以很方便的实现listView、gridView的功能,非常的方便,还有额外的瀑布流效果,使用习惯后我也相信你会喜欢这样的新控件。
RecyclerView 设置 Item 点击事件
这里只实现item的单击事件,因为item的长按事件也是一样。两个我就实现一个,另外一个也是依葫芦画瓢。理解才能更好的使用,大家一定要好好掌握,看我在代码中的注释去慢慢的分析掌握这部分,会对你很有用的,因为很多场景都可以借鉴该方法来获取数据(也就是回调)。
- 声明 MyItemClickListener 接口如下:
package com.example.administrator.recyclerviewdemo;
import android.view.View;
/**
* 接口中声明一个item的点击事件方法,参数带 View对象 和 item的位置
*/
public interface MyItemClickListener {
void onItemClick(View view, int position);// 声明item点击方法
}
- 在adapter中写方法用来注册 MyItemClickListener 监听器,如下:
// 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{
private List<String> listData;
private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度
private MyItemClickListener listener;
private MyItemClickListener onItemClickListener;
public MyRecyclerViewAdapter(List<String> listTemp) {
this.listData = listTemp;
getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
}
/**
* 提供给开发者调用,注册监听器
* @param listener
*/
public void setMyItemClickListener(MyItemClickListener listener){
this.listener = listener;
}
/**
* 随机高度设置
* @param length item的个数
*/
public void getRandomHeight(int length){
heightList = new ArrayList<>();
for (int i = 0;i < length;i++){
int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
heightList.add(randomH);
}
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// 使用布局泵构建itemView的布局
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
// 创建MyViewHolder对象
MyViewHolder holder = new MyViewHolder(view);
// 返回MyViewHolder对象
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
// 给瀑布流效果的item设置随机高度
ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
params.height = heightList.get(position);
holder.tv_content.setLayoutParams(params);
String content = listData.get(position);// 获取数据
holder.tv_content.setText(content);// 给item设置数据
}
@Override
public int getItemCount() {
return listData.size();// 返回item的个数
}
/**
* 创建MyViewHolder继承RecyclerView.ViewHolder
* 在内部方法MyViewHolder中缓存itemView中的控件
*/
class MyViewHolder extends RecyclerView.ViewHolder{
TextView tv_content;// itemView中的 TextView 控件
public MyViewHolder(View itemView) {
super(itemView);
// 缓存控件
tv_content = itemView.findViewById(R.id.tv_content);
}
}
}
- 然后在 onCreateViewHolder 方法中,创建MyViewHolder对象的时候,通过构造方法将 listener
监听器对象传递给 MyViewHolder,然后在 MyViewHolder 类中itemView的点击事件中调用 listener
的方法即可。如下:
// 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{
private List<String> listData;
private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度
private MyItemClickListener listener;
private MyItemClickListener onItemClickListener;
public MyRecyclerViewAdapter(List<String> listTemp) {
this.listData = listTemp;
getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
}
/**
* 提供给开发者调用,注册监听器
* @param listener
*/
public void setMyItemClickListener(MyItemClickListener listener){
this.listener = listener;
}
/**
* 随机高度设置
* @param length item的个数
*/
public void getRandomHeight(int length){
heightList = new ArrayList<>();
for (int i = 0;i < length;i++){
int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
heightList.add(randomH);
}
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// 使用布局泵构建itemView的布局
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
// 创建MyViewHolder对象
MyViewHolder holder = new MyViewHolder(view, listener);
// 返回MyViewHolder对象
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
// 给瀑布流效果的item设置随机高度
ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
params.height = heightList.get(position);
holder.tv_content.setLayoutParams(params);
String content = listData.get(position);// 获取数据
holder.tv_content.setText(content);// 给item设置数据
}
@Override
public int getItemCount() {
return listData.size();// 返回item的个数
}
/**
* 创建MyViewHolder继承RecyclerView.ViewHolder
* 在内部方法MyViewHolder中缓存itemView中的控件
*/
class MyViewHolder extends RecyclerView.ViewHolder{
TextView tv_content;// itemView中的 TextView 控件
public MyViewHolder(final View itemView, final MyItemClickListener listener) {
super(itemView);
// 缓存控件
tv_content = itemView.findViewById(R.id.tv_content);
// item单击实现
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null){
listener.onItemClick(itemView, getAdapterPosition());
}
}
});
}
}
}
- 到这里准备工作就做好了,下面是我们开发者的工作了,我们只需要注册这个监听器即可,如下:
// recyclerView 的item单击事件监听实现
adapter.setMyItemClickListener(new MyItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, "开发者点击了:"+ list.get(position), Toast.LENGTH_LONG).show();
}
});
最后给出完整的代码,如下:
package com.example.administrator.recyclerviewdemo;
import android.app.Activity;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends Activity{
@BindView(R.id.rv_demo)RecyclerView rv_demo;// RecyclerView控件
private List<String> list = new ArrayList<>();
private MyRecyclerViewAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
initData();// 初始化模拟数据
setListeners();// 设置监听
}
/**
* 设置监听
*/
private void setListeners() {
// recyclerView 的item单击事件监听实现
adapter.setMyItemClickListener(new MyItemClickListener() {
@Override
public void onItemClick(View view, int position) {
Toast.makeText(MainActivity.this, "开发者点击了:"+ list.get(position), Toast.LENGTH_LONG).show();
}
});
}
/**
* 初始化数据
*/
private void initData() {
for (int i = 0;i < 40;i++){
list.add("demo item" + (i+1));
}
show();// 使用 RecyclerView 展示数据
}
/**
* 使用recyclerView展示数据
*/
private void show() {
// 第一步:创建 MyRecyclerViewAdapter
adapter = new MyRecyclerViewAdapter(list);
// 第二步:设置布局管理器,控制布局效果
// 线性垂直布局
// rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.VERTICAL, false));
// 线性水平布局
// rv_demo.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL, false));
// 网格布局
// rv_demo.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));
// 瀑布流布局
rv_demo.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
// 第三步:设置adapter
rv_demo.setAdapter(adapter);
rv_demo.setItemAnimator(new DefaultItemAnimator());// 设置系统默认的动画效果
}
// 第一步:继承重写 RecyclerView.Adapter 和 RecyclerView.ViewHolder
class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{
private List<String> listData;
private List<Integer> heightList;// 瀑布流效果使用,用于保存生产的随机高度
private MyItemClickListener listener;
private MyItemClickListener onItemClickListener;
public MyRecyclerViewAdapter(List<String> listTemp) {
this.listData = listTemp;
getRandomHeight(listTemp.size());// 随机高度设置,瀑布流效果的recyclerView有用
}
/**
* 提供给开发者调用,注册监听器
* @param listener
*/
public void setMyItemClickListener(MyItemClickListener listener){
this.listener = listener;
}
/**
* 随机高度设置
* @param length item的个数
*/
public void getRandomHeight(int length){
heightList = new ArrayList<>();
for (int i = 0;i < length;i++){
int randomH = new Random().nextInt(400) + 200;// 200-600之间的随机int类型数值
heightList.add(randomH);
}
}
@NonNull
@Override
public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
// 使用布局泵构建itemView的布局
View view = LayoutInflater.from(MainActivity.this).inflate(R.layout.recyclerview_item_demo, parent, false);
// 创建MyViewHolder对象
MyViewHolder holder = new MyViewHolder(view, listener);
// 返回MyViewHolder对象
return holder;
}
@Override
public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
// 给瀑布流效果的item设置随机高度
ViewGroup.LayoutParams params = holder.tv_content.getLayoutParams();
params.height = heightList.get(position);
holder.tv_content.setLayoutParams(params);
String content = listData.get(position);// 获取数据
holder.tv_content.setText(content);// 给item设置数据
}
@Override
public int getItemCount() {
return listData.size();// 返回item的个数
}
/**
* 创建MyViewHolder继承RecyclerView.ViewHolder
* 在内部方法MyViewHolder中缓存itemView中的控件
*/
class MyViewHolder extends RecyclerView.ViewHolder{
TextView tv_content;// itemView中的 TextView 控件
public MyViewHolder(final View itemView, final MyItemClickListener listener) {
super(itemView);
// 缓存控件
tv_content = itemView.findViewById(R.id.tv_content);
// item单击实现
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null){
listener.onItemClick(itemView, getAdapterPosition());
}
}
});
}
}
}
}
运行后的效果图示如下:
总结
这里简单的讲了recyclerView 的简单使用,并给大家实现了 item点击事件。你只要掌握了这篇文章,那么你应该可以在项目中很熟练的使用 RecyclerView了。
RecyclerView 远不止我现在介绍的这些,还有很多其他的可扩展的功能,只能开发者在以后的实战中自己去慢慢掌握和学习了。加油哦!
A little bit of progress every day!Come on!