ListView功能是很强大的,直到现在还有很多程序在继续使用着ListView。不过ListView并不是没有缺点的,比如当数据量非常大的时候,如果不使用一些技巧提升它的运行效率,那么ListView的性能会非常差的。还有,ListView的扩展性也不够好,他只能实现数据纵向滚动的效果,如果想实现横向滚动的话,ListView是做不到的。
那么这时就需要一个更强大的滚动控件——RecyclerView。它可以说是一个增强版的ListView,不仅可以轻松实现和ListView同样的效果,还有优化了ListView中存在的各种不足之处。
RecyclerView的基本使用
首先在app的build.gradle中添加依赖:
implementation 'com.android.support:recyclerview-v7:26.1.0'
接着在activity_main.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:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
然后为RecyclerView准备一个适配器:
/**
* Created by Layne_Yao on 2018/6/8.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private List<Person> personList;
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView imgPortrait;
TextView tvName, tvFruitAbility;
/**
* ViewHolder的构造方法
* @param itemView 这个布局是RecyclerView子项最外层的布局
*/
public ViewHolder(View itemView) {
super(itemView);
imgPortrait = itemView.findViewById(R.id.imgPortrait);
tvName = itemView.findViewById(R.id.tvName);
tvFruitAbility = itemView.findViewById(R.id.tvFruitAbility);
}
}
/**
* RecyclerViewAdapter的构造方法,
* @param personList 传入的数据源
*/
public RecyclerViewAdapter(List<Person> personList) {
this.personList = personList;
}
/**
* 此方法用于创建ViewHolder实例,并将要加载的布局传入到构造函数中
* @param parent
* @param viewType
* @return
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_person, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
/**
* 此方法用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Person person = personList.get(position);
holder.imgPortrait.setImageResource(person.getPortrait());
holder.tvName.setText(person.getName());
holder.tvFruitAbility.setText(person.getFruitAbility());
}
/**
* 告诉RecyclerView一共有多少个子项
* @return
*/
@Override
public int getItemCount() {
return personList.size();
}
}
上面会用到一个Person的实体类:
/**
* Created by Layne_Yao on 2018/5/28.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class Person {
private int portrait;
private String name;
private String fruitAbility;
public Person(int portrait, String name, String fruitAbility) {
this.portrait = portrait;
this.name = name;
this.fruitAbility = fruitAbility;
}
public int getPortrait() {
return portrait;
}
public void setPortrait(int portrait) {
this.portrait = portrait;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFruitAbility() {
return fruitAbility;
}
public void setFruitAbility(String fruitAbility) {
this.fruitAbility = fruitAbility;
}
}
还缺一个item_person的子布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="@+id/imgPortrait"
android:layout_width="50dp"
android:layout_height="50dp" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:orientation="vertical"
android:paddingLeft="8dp">
<TextView
android:id="@+id/tvName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#333333"
android:textSize="16sp" />
<TextView
android:id="@+id/tvFruitAbility"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#888888"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
最后就是MainActivity.java的代码实现:
public class MainActivity extends AppCompatActivity {
private List<Person> personList;
private RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
recyclerView = findViewById(R.id.recyclerView);
//纵向布局
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(personList);
recyclerView.setAdapter(adapter);
}
private void initData() {
personList = new ArrayList<>();
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
}
}
就这样最基本的显示就完成了,运行结果如下:
上面是最简单的数据展示了,RecyclerView其实还有很多布局,上面是纵向布局LinearLayoutManager,还可以切换成横向布局,瀑布流布局StaggeredGridLayoutManager和网格布局GridLayoutManager。
里就不一一说明,直接在上面的例子改成个布局的切换,以及item的点击事件。
点击事件要改的是适配器里面的代码:
/**
* Created by Layne_Yao on 2018/6/8.
* CSDN:http://blog.csdn.net/Jsagacity
*/
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private List<Person> personList;
static class ViewHolder extends RecyclerView.ViewHolder {
View personView;
ImageView imgPortrait;
TextView tvName, tvFruitAbility;
/**
* ViewHolder的构造方法
* @param itemView 这个布局是RecyclerView子项最外层的布局
*/
public ViewHolder(View itemView) {
super(itemView);
personView = itemView;
imgPortrait = itemView.findViewById(R.id.imgPortrait);
tvName = itemView.findViewById(R.id.tvName);
tvFruitAbility = itemView.findViewById(R.id.tvFruitAbility);
}
}
/**
* RecyclerViewAdapter的构造方法,
* @param personList 传入的数据源
*/
public RecyclerViewAdapter(List<Person> personList) {
this.personList = personList;
}
/**
* 此方法用于创建ViewHolder实例,并将要加载的布局传入到构造函数中
* @param parent
* @param viewType
* @return
*/
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_person, parent, false);
final ViewHolder holder = new ViewHolder(view);
//子项的点击事件
holder.personView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = holder.getAdapterPosition();
Person person = personList.get(position);
Toast.makeText(view.getContext(),position+":"+person.getName(),Toast.LENGTH_SHORT).show();
}
});
//图片的点击事件
holder.imgPortrait.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = holder.getAdapterPosition();
Person person = personList.get(position);
Toast.makeText(view.getContext(),position+":"+person.getName(),Toast.LENGTH_SHORT).show();
}
});
return holder;
}
/**
* 此方法用于对RecyclerView子项的数据进行赋值的,会在每个子项被滚动到屏幕内的时候执行
* @param holder
* @param position
*/
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Person person = personList.get(position);
holder.imgPortrait.setImageResource(person.getPortrait());
holder.tvName.setText(person.getName());
holder.tvFruitAbility.setText(person.getFruitAbility());
}
/**
* 告诉RecyclerView一共有多少个子项
* @return
*/
@Override
public int getItemCount() {
return personList.size();
}
}
MainActivity中的代码修改成:
public class MainActivity extends AppCompatActivity {
private List<Person> personList;
private RecyclerView recyclerView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
recyclerView = findViewById(R.id.recyclerView);
//纵向布局
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
RecyclerViewAdapter adapter = new RecyclerViewAdapter(personList);
recyclerView.setAdapter(adapter);
}
private void initData() {
personList = new ArrayList<>();
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
personList.add(new Person(R.drawable.aisi, "艾斯", "烧烧果实,控制火的能力"));
personList.add(new Person(R.drawable.lufei, "路飞", "橡皮果实,是一个橡皮人"));
personList.add(new Person(R.drawable.luo, "罗", "手术果实,是一个很厉害的医生"));
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add(0, 1, 0, "切换LinearLayoutManager");
menu.add(0, 2, 0, "切换成横向布局");
menu.add(0, 3, 0, "切换StaggeredGridLayoutManager");
menu.add(0, 4, 0, "切换GridLayoutManager");
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case 1:
//纵向布局
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
break;
case 2:
LinearLayoutManager layoutManager1 = new LinearLayoutManager(this);
//横向布局
layoutManager1.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager1);
break;
case 3:
//瀑布流布局
StaggeredGridLayoutManager layoutManager2 = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager2);
break;
case 4:
//网格布局
GridLayoutManager layoutManager3 = new GridLayoutManager(this, 2);
recyclerView.setLayoutManager(layoutManager3);
break;
}
return true;
}
}
运行结果:
源码已经全部贴出来了,所以就不提供源码下载了