一个RecyclerView的案例和解析
之前介绍了ListView的使用,如果在使用ListView的时候不使用一些技巧,listView的性能是不好的,而且它的扩展性也不好,只能支持纵向滚动效果,如果想实现横向的滚动效果,ListView是无法实现的。因此Android 提供了一个更强大的滚动控件RecyclerView, 它不仅能实现与ListView相同的效果,同时也补充了ListView的不足之处。
开始介绍RecyclerView的使用
RecyclerView是定义在support库中的新增的控件,所以使用的时候需要在项目的build.gradle文件中dependencies闭包中添加依赖
compile 'com.android.support:recyclerview-v7:26.0.0-alpha1', 添加完后,需要点击Sync now 进行同步。
如下:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
testCompile 'junit:junit:4.12'
}
API代码引入后,就可以正常使用,RecyclerView的实现略微复杂,但是代码清晰容易理解。
UI布局
Activity_main.xml 中使用RecyclerView标签的时候要添加完整包名,因为它并不在内置的sdk系统中,然后设定id, 并且配置高度和宽度都是match_parent,这样RecyclerView将充满整个布局空间。
Fruit_item.xml 中实现了RecyclerView子项的布局设计,如下代码所示:
数据填充
1- 首先也是定义数据类, Fruit.xml
public class Fruit {
private String name;
private int imageID;
public Fruit(String name, int imageID){
this.name=name;
this.imageID=imageID;
}
public int getImageID() {
return imageID;
}
public String getName() {
return name;
}
}
2- 其次就是适配器的实现,FruitAdapter.java - RecyclerView的适配器需要继承RecyclerView.Adapter,并将泛型指定为FruitAdapter.ViewHolder,其中viewHolder是FruitAdapter的一个内部类。
代码详解如下
package com.motorola.recyclerviewtest;
import android.provider.ContactsContract;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import org.w3c.dom.Text;
import java.util.ArrayList;
import java.util.List;
public class FruitAdapter extends RecyclerView.Adapter {
private List mFruitList;
static class ViewHolder extends RecyclerView.ViewHolder {
private View fruitView;
private ImageView fruit_image;
private TextView fruit_name;
public ViewHolder(View itemView) {
super(itemView);
fruitView=itemView;
fruit_image = (ImageView) itemView.findViewById(R.id.fruit_image);
fruit_name = (TextView) itemView.findViewById(R.id.fruit_name);
}
}
public FruitAdapter(List fruits) {
this.mFruitList = fruits;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
final ViewHolder viewHolder = new ViewHolder(view);
viewHolder.fruitView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int postion = viewHolder.getAdapterPosition();
Fruit fruit =mFruitList.get(postion);
Toast.makeText(view.getContext(), "You click "+fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
viewHolder.fruit_image.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
int position= viewHolder.getAdapterPosition();
Fruit fruit=mFruitList.get(position);
Toast.makeText(view.getContext(), "You click " +fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
return viewHolder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Fruit fruit = mFruitList.get(position);
holder.fruit_image.setImageResource(fruit.getImageID());
holder.fruit_name.setText(fruit.getName());
}
@Override
public int getItemCount() {
return mFruitList.size();
}
}
ViewHolder:
ViewHolder 内部类需要继承RecyclerView.ViewHolder,然后ViewHolder的构造函数中需要传入一个View参数,这个参数就是RecyclerView子项的最外层布局,接下来就可以通过findViewById
()方法来获取布局中ImageView和TextView实例。
FruitAdapter类继承自RecyclerView.Adapter,在该类构造函数中需要传输数据源,接下来的各种操作都是基于数据源操作的。同时需要重写RecyclerView.Adapter的三个方法onCreateViewHolder(), onBindViewHolder(), getItemCount()
- onCreateViewHolder(): 这个方法是用于创建viewHolder实例的,首先调用LayoutInflater去加载fruit_item子布局到父布局中,然后将创建的布局View实例作为参数传入ViewHolder构造中,创建ViewHolder实例。
如下代码所示:
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
final ViewHolder viewHolder = new ViewHolder(view);
- onBindViewHolder(): 这个方法主要用于对RecyclerView的子项进行数据赋值。如下代码所示
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Fruit fruit = mFruitList.get(position);
holder.fruit_image.setImageResource(fruit.getImageID());
holder.fruit_name.setText(fruit.getName());
}
- getItemCount(): 这个方法很简单,用于告诉RecyclerView总共有多少个子项,直接获取数据源的长度就可以得到了。如下代码所示
@Override
public int getItemCount() {
return mFruitList.size();
}
到这里适配器类就实现好了,整体代码如下所示:
RecyclerView的运用
MainActivity.javapackage com.motorola.recyclerviewtest;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
private List mFruitList = new ArrayList();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initFruit();
RecyclerView recyclerView=(RecyclerView)findViewById(R.id.Recyclerview1);
// LinearLayoutManager linearLayoutManager=new LinearLayoutManager(this);
// linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
StaggeredGridLayoutManager layoutManager=new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(new FruitAdapter(mFruitList));
}
public void initFruit(){
for(int i=0; i<5; i++){
Fruit apple = new Fruit(getRandomLengthName("apple"), R.drawable.picture1);
mFruitList.add(apple);
Fruit pear = new Fruit(getRandomLengthName("pear"), R.drawable.picture2);
mFruitList.add(pear);
Fruit watermelon = new Fruit(getRandomLengthName("watermelon"), R.drawable.picture3);
mFruitList.add(watermelon);
Fruit peach = new Fruit(getRandomLengthName("peach"), R.drawable.picture4);
mFruitList.add(peach);
Fruit strawberry = new Fruit(getRandomLengthName("strawberry"), R.drawable.picture5);
mFruitList.add(strawberry);
Fruit mango = new Fruit(getRandomLengthName("mango"), R.drawable.picture6);
mFruitList.add(mango);
Fruit cherry = new Fruit(getRandomLengthName("cherry"), R.drawable.picture7);
mFruitList.add(cherry);
Fruit grape = new Fruit(getRandomLengthName("grape"), R.drawable.picture8);
mFruitList.add(grape);
}
}
private String getRandomLengthName(String name){
Random random = new Random();
int length =random.nextInt(20)+1;
StringBuilder stringBuilder= new StringBuilder();
for(int i=0;i
在mainActivity.java类中,Oncreate() 方法下,首先创建RecyclerView的对象,然后创建一个LinearlayoutManager 布局管理器对象,并把它设置到RecyclerView的对象当中,然后再通过setAdapter()
方法将fruitadapter对象设置到Recyclerview对象中,LinearlayoutManager 是用于设置RecyclerView的布局管理器,可以设置LinearLayoutManager 对象的setOrientation()
方法参数为LinearLayoutManager.HORIZONTAL, 这样RecyclerView的排列方式就转化成了横向排列。
除了LinearLayoutManager 布局之外,RecyclerView还提供了GridLayoutManager, StaggeredGridLayoutManager. GridLayoutManager实现的是网格布局,StaggeredGrid
LayoutManager实现的瀑布流布局.
点击事件
RecyclerView 的点击事件的实现要比ListView的复杂得多,但是却更灵活的提供了针对不同控件的点击要求。
在ListView中,控件直接提供了方法setOnItemClickListener(), 而RecyclerView的实现是在适配器的方法onCreateViewHolder()中,当获取到ViewHolder对象后,针对每一个控件对象都可以实现点击事件,这里实现了最外层布局和ImageView的点击事件。
如下代码所示:
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fruit_item, parent, false);
final ViewHolder viewHolder = new ViewHolder(view);
viewHolder.fruitView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int postion = viewHolder.getAdapterPosition();
Fruit fruit =mFruitList.get(postion);
Toast.makeText(view.getContext(), "You click "+fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
viewHolder.fruit_image.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
int position= viewHolder.getAdapterPosition();
Fruit fruit=mFruitList.get(position);
Toast.makeText(view.getContext(), "You click " +fruit.getName(), Toast.LENGTH_SHORT).show();
}
});
return viewHolder;
}