RecycleView
本文介绍
- 实现了RecycleView的三种布局,线性布局,网格布局,瀑布流布局
- 适配器和Activity基本每条语句都有注释
- 还有适配器中,在两个方法中设置点击事件的比较:
在Adapter.onBindViewHolder()中设置点击事件:
优点:可以直接获取位置,有position参数
缺点:会为当前显示的以及缓存的View都设置一个Listener回调,浪费内存。
在onCreateViewHolder()中设置点击事件:
优点:View复用,不浪费内存
缺点:没有position参数,需要自己获取位置
1. 效果图
线性布局
网格布局
瀑布流布局
2. 添加依赖
//recycleview
implementation 'androidx.recyclerview:recyclerview:1.1.0'
3. 布局
activity_recycleview
<?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:layout_height="match_parent"
tools:context=".recycleview.RecycleViewActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycleview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
item_for_recycleview
<?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:layout_margin="5dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/picture"
android:layout_marginRight="10dp"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/shuguang"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="vertical">
<TextView
android:id="@+id/name"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="@string/String1"
android:textSize="16sp"
android:textColor="@color/red"/>
<TextView
android:id="@+id/qname"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:text="@string/String2"
android:textSize="12sp"
android:textColor="@color/gray_cc"/>
</LinearLayout>
</LinearLayout>
4. 实体类
Friends
/**
* create by 星航指挥官
* create on 2020/8/29
* 我为天帝 当镇压世间一切敌
* 遮天
*/
public class Friends {
private int picture;
private String name;
private String qname;
public Friends() {
}
public Friends(int picture, String name, String qname) {
this.picture = picture;
this.name = name;
this.qname = qname;
}
public int getPicture() {
return picture;
}
public void setPicture(int picture) {
this.picture = picture;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getQname() {
return qname;
}
public void setQname(String qname) {
this.qname = qname;
}
}
5. 适配器
FriendsAdapter
/**
* create by 星航指挥官
* create on 2020/8/29
* 我为天帝 当镇压世间一切敌
* 遮天
*/
public class FriendsAdapter extends RecyclerView.Adapter<FriendsAdapter.ViewHolder> {
private static final String TAG = "FriendsAdapter";
//创建一个全局变量,存储数据源,以便进行后续操作
private List<Friends> friendsList;
/*
*创建内部类ViewHolder继承RecyclerView.ViewHolder
* ViewHolder的构造器要传入一个View参数
* 用来获取自定义布局中的对象
*/
static class ViewHolder extends RecyclerView.ViewHolder{
//保存布局实例
View view;
//声明自定义布局中的控件
ImageView picture;
TextView name;
TextView qname;
public ViewHolder(@NonNull View itemView) {
super(itemView);
//保存布局实例
view = itemView;
//获取控件
picture = itemView.findViewById(R.id.picture);
name = itemView.findViewById(R.id.name);
qname = itemView.findViewById(R.id.qname);
}
}
/*
* 适配器的构造方法
* 主要用于将要展示的数据传入
* 然后存储到全局变量中
* */
public FriendsAdapter(List<Friends> friendsList) {
this.friendsList = friendsList;
}
/*
* 继承RecyclerView.Adapter必须要重写
* 该方法主要用于创建ViewHolder实例
* */
@NonNull
@Override
public FriendsAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//加载自定义布局
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_for_recycleview,parent,false);
//将布局传入ViewHolder的构造器获得ViewHolder实例
ViewHolder holder = new ViewHolder(view);
//为控件设置监听
holder.picture.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取当前位置
int position = holder.getAdapterPosition();
//通过位置获取数据源实例
Friends friend = friendsList.get(position);
//Toast
ToastUtils.showToast(v.getContext(),"你点击了"+friend.getName()+"的头像");
}
});
holder.name.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取当前位置
int position = holder.getAdapterPosition();
//通过位置获取数据源实例
Friends friend = friendsList.get(position);
//Toast
ToastUtils.showToast(parent.getContext(),"你点击了"+friend.getName());
}
});
holder.qname.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取当前位置
int position = holder.getAdapterPosition();
//通过位置获取数据源实例
Friends friend = friendsList.get(position);
//Toast
ToastUtils.showToast(parent.getContext(),"你点击了"+friend.getName()+"的签名");
}
});
//返回ViewHolder实例
return holder;
}
/*
* 继承RecyclerView.Adapter必须要重写
* 该方法主要用于对RecycleView的子项进行赋值
* 会在每个子项被滚动到屏幕内的时候执行
* */
@Override
public void onBindViewHolder(@NonNull FriendsAdapter.ViewHolder holder, int position) {
//通过position参数得到当前项的数据源实列
Friends friends = friendsList.get(position);
//然后将实例的数据设置到ViewHolder声明的控件中
holder.picture.setImageResource(friends.getPicture());
holder.name.setText(friends.getName());
holder.qname.setText(friends.getQname());
}
/*
* 继承RecyclerView.Adapter必须要重写
* 该方法主要用于返回RecycleView子项的数量
* 直接返回数据源的长度就可以了
* */
@Override
public int getItemCount() {
return friendsList.size();
}
}
6. Activity
RecycleViewActivity
/**
* create by 星航指挥官
* create on 2020/8/29
* 我为天帝 当镇压世间一切敌
* 遮天
*/
public class RecycleViewActivity extends BaseActivity {
private static final String TAG = "RecycleViewActivity";
List<Friends> friendsList = new ArrayList<>();
@BindView(R.id.recycleview)
RecyclerView recycleview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycleview);
ButterKnife.bind(this);
initFriends();
setRecycleView();
}
/*
* 数据源
* */
private String[] qname = {"劫过九重城关", "我座下马正酣", "看那轻飘飘的衣摆", "趁擦肩把裙掀",
"踏遍三江六岸", "借刀光做船帆", "任露水浸透了短衫", "大盗睥睨四野",
"枕风宿雪多年", "我与虎谋早餐", "拎着钓叟的鱼弦", "问卧龙几两钱",
"蜀中大雨连绵", "关外横尸遍野", "你的笑像一条恶犬", "撞乱了我心弦"};
private String[] name = {"星航指挥官", "大盗", "女贼", "公主",
"女帝", "大帝", "路人", "小猫",
"妖妖", "水色涟漪", "一米阳光", "往事随风",
"时光清浅", "大梦一场", "帝三岁", "林keke"};
/*
* 数据源
* */
private void initFriends() {
//初始化数据源
Friends friends;
for (int i = 0; i < 16; i++) {
friends = new Friends();
friends.setPicture(R.drawable.shuguang);
friends.setName(name[i]);
if (i % 2 == 0)
friends.setQname(qname[i]);
else
friends.setQname(qname[i] + qname[i] + qname[i]);
friendsList.add(friends);
}
}
/*
* 给RecycleView设置布局和适配器
* */
private void setRecycleView() {
//线性布局:layoutManager
LinearLayoutManager layoutManager1 = new LinearLayoutManager(this);
//layoutManager1.setOrientation(RecyclerView.HORIZONTAL);//setOrientation()控制方向,默认垂直
//网格布局:GridLayoutManager
GridLayoutManager layoutManager2 = new GridLayoutManager(this, 3);
//瀑布流布局:StaggeredGridLayoutManager
StaggeredGridLayoutManager layoutManager3 = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
//设置recycle布局管理器
recycleview.setLayoutManager(layoutManager1);
//创建Adapter实例
FriendsAdapter adapter = new FriendsAdapter(friendsList);
//给RecycleView设置适配器
recycleview.setAdapter(adapter);
}
}
避坑
在Fragment使用小刀注解的时候,导致控件不会自动绑定,缺少一条语句
ButterKnife.bind(this,view);
如果不手动添加 则会报异常
Attempt to invoke virtual method ‘void androidx.recyclerview.widget.RecyclerView.setLayoutManager(androidx.recyclerview.widget.RecyclerView$LayoutManager)’ on a null object reference
kee