一、RecyclerView的概念
Android提供了一个更强大的滚动控件——RecyclerView。 它可以说是一个增强版的ListView, 不仅可以轻松实现和ListView同样的效果, 还优化了ListView中存在的各种不足之处。 目前Android官方更加推荐使用RecyclerView, 未来也会有更多的程序逐渐从ListView转向RecyclerView。
二、RecycleView的简单使用
1、 先写好布局文件
添加RecyclerView控件
代码如下
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/fruit_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
添加RecyclerView的内容子项,新建一个布局文件,命名为 item_XXX.xml
其中编写RecyclerView中的子项布局样式,以一个图片,然后加图片名字为例
代码如下
<?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="match_parent">
<ImageView
android:id="@+id/fruit_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/fruit_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="#aaffcc"
android:layout_marginTop="10dp"/>
</LinearLayout>
2、写好相应的java文件
首先创建子项的实体类(以子项为水果,水果图片为例)
创建Fruit.class
public class Fruit {
private String fruitName;
private int fruitImageID;
public String getFruitName() {
return fruitName;
}
public void setFruitName(String fruitName) {
this.fruitName = fruitName;
}
public int getFruitImageID() {
return fruitImageID;
}
public void setFruitImageID(int fruitImageID) {
this.fruitImageID = fruitImageID;
}
public Fruit(String fruitName, int fruitImageID) {
this.fruitName = fruitName;
this.fruitImageID = fruitImageID;
}
}
其次创建对应的适配器
创建FruitAdapter类,继承Adapter类,并且指定泛型为FruitAdapter.ViewHolder。
FruitAdapter继承RecyclerView.Adapter,必须重写onCreateViewHolder(),onBindViewHolder()和getItemCount()三个方法。
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class FruitAdapter extends RecyclerView.Adapter <FruitAdapter.ViewHolder>{
private List<Fruit> mFruitList;
//FruitAdapter构造函数,用于把要展示的数据源传入,并赋予值给类的私有变量mFruitList
public FruitAdapter(List<Fruit> fruitList){
mFruitList = fruitList;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
//onCreateViewHolder() 方法是用于创建ViewHolder 实例的, 我们在这个方法中将item_Fruit 布局加载进来, 然后创建一个ViewHolder 实例, 并把加载出来的布局传入到构造函数当中, 最后将ViewHolder 的实例返回。
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_fruit_recycler_view,parent,false);
ViewHolder viewHolder = new ViewHolder(view);
return viewHolder;
}
@Override
public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
//onBindViewHolder() 方法是用于对RecyclerView子项的数据进行赋值的, 会在每个子项被滚动到屏幕内的时候执行, 这里我们通过position 参数得到当前项的Fruit实例, 然后再将数据设置到ViewHolder 的ImageView和TextView当中即可。
Fruit fruit = mFruitList.get(position);
viewHolder.fruitImage.setImageResource(fruit.getFruitImageID());
viewHolder.fruitName.setText(fruit.getFruitName());
}
@Override
public int getItemCount() {
//getItemCount() 方法就非常简单了, 它用于告诉RecyclerView一共有多少子项, 直接返回数据源的长度就可以了。
return mFruitList.size();
}
//定义内部类ViewHolder,并继承RecyclerView.ViewHolder传入View参数通常是Recycler View子项的最外层布局
public class ViewHolder extends RecyclerView.ViewHolder {
ImageView fruitImage;
TextView fruitName;
public ViewHolder(@NonNull View itemView) {
super(itemView);
fruitImage = itemView.findViewById(R.id.fruit_image);
fruitName = itemView.findViewById(R.id.fruit_name);
}
}
}
最后修改MainActivity文件带代码
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.widget.RelativeLayout;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private List<Fruit> fruitList = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruitList();
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.fruit_recycler_view);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
FruitAdapter adapter = new FruitAdapter(fruitList);
recyclerView.setAdapter(adapter);
}
private void initFruitList(){
for(int i = 0 ; i < 10 ; i++){
Fruit apple = new Fruit("apple",R.drawable.pingguo);
fruitList.add(apple);
Fruit caomei = new Fruit("caomei",R.drawable.caomei);
fruitList.add(caomei);
Fruit chengzi = new Fruit("chengzi",R.drawable.chengzi);
fruitList.add(chengzi);
Fruit lizi = new Fruit("lizi",R.drawable.lizi);
fruitList.add(lizi);
Fruit lanmei = new Fruit("lanmei",R.drawable.lanmei);
fruitList.add(lanmei);
Fruit mangguo = new Fruit("mangguo",R.drawable.mangguo);
fruitList.add(mangguo);
Fruit putao = new Fruit("putao",R.drawable.putao);
fruitList.add(putao);
Fruit xiangjiao = new Fruit("xiangjiao",R.drawable.xiangjiao);
fruitList.add(xiangjiao);
Fruit xigua = new Fruit("xigua",R.drawable.xigua);
fruitList.add(xigua);
Fruit yingtao = new Fruit("yingtao",R.drawable.yingtao);
fruitList.add(yingtao);
}
}
}
initFruit用来创建Fruit实例,然后LayoutManager用于指定RecyclerView的布局方式, 这里使用的LinearLayoutManager是线性布局的意思(还有横向布局、网格布局等不同的布局样式), 可以实现和ListView类似的效果。 接下来我们创建了FruitAdapter 的实例, 并将创建的FruitList数据传入到FruitAdapter 的构造函数中, 最后调用RecyclerView的setAdapter() 方法来完成适配器设置, 这样RecyclerView和数据之间的关联就建立完成了。
其他布局方式
横向布局
MainActivity中只加入了一行代码, 调用LinearLayoutManager的setOrientation() 方法来设置布局的排列方向, 默认是纵向排列的, 我们传入LinearLayoutManager.HORIZONTAL 表示让布局横行排列, 这样RecyclerView就可以横向滚动了。
网格布局
在MainActivity中使用StaggeredGridLayoutManager,最后调用RecyclerView的setAdapter()方法来完成适配设置即可。
点击事件
RecyclerView比ListView的很大一个区别就是RecyclerView中的所有子项都是可以触发点击事件的
在类FruitAdapter中的onCreateViewHolder方法中,给每个子项的小控件注册点击监听器,从而实现点击事件。
viewHolder.fruitImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("1111111111111111", "onClick: "+R.id.fruit_image);
}
});
viewHolder.fruitName.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.d("1111111111111111", "onClick: "+R.id.fruit_name);
}
});
return viewHolder;