由于ListView只能实现数据纵向(垂直)方向的滚动效果,不能实现横向(水平)方向的滚动效果。因此,android官方更加推荐使用RecyclerView。
RecyclerView可以说是ListView的加强版,不仅可以实现和ListView同样的效果,还优化了ListView的不足之处,同时具有很好的扩展性(实现横向布局,网格布局,瀑布流布局)
RecyclerView是android新增的控件,为了能在所有android版本上使用,需要将它定义在support库中,即在项目的build.gradle中添加相应的依赖库。
实例:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.sky.recyclerviewdemo.MainActivity"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/btnVertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Vertical Layout"
android:textAllCaps="false"/>
<Button
android:id="@+id/btnHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Horizontal Layout"
android:textAllCaps="false"/>
<Button
android:id="@+id/btnGrid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Grid Layout"
android:textAllCaps="false"/>
<Button
android:id="@+id/btnStaggered"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Staggered Grid Layout"
android:textAllCaps="false"/>
LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button btnVertical;
private Button btnHorizontal;
private Button btnGrid;
private Button btnStaggered;
private Intent intent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
btnVertical = (Button)findViewById(R.id.btnVertical);
btnHorizontal = (Button)findViewById(R.id.btnHorizontal);
btnGrid = (Button)findViewById(R.id.btnGrid);
btnStaggered = (Button)findViewById(R.id.btnStaggered);
btnVertical.setOnClickListener(this);
btnHorizontal.setOnClickListener(this);
btnGrid.setOnClickListener(this);
btnStaggered.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btnVertical:
intent = new Intent(MainActivity.this, VerticalActivity.class);
startActivity(intent);
break;
case R.id.btnHorizontal:
intent = new Intent(MainActivity.this, HorizontalActivity.class);
startActivity(intent);
break;
case R.id.btnGrid:
intent = new Intent(MainActivity.this, GridActivity.class);
startActivity(intent);
break;
case R.id.btnStaggered:
intent = new Intent(MainActivity.this, StaggeredActivity.class);
startActivity(intent);
break;
default:
}
}
}
一、RecyclerView的基本用法(垂直布局)
主界面布局:activity_vertical.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.sky.recyclerviewdemo.VerticalActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/vertical_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
LinearLayout>
RecyclerView代码实现VerticalActivity.class
public class VerticalActivity extends AppCompatActivity {
private List picList = new ArrayList<>();
// 数据资源
private int[] data = {
R.drawable.pic_1, R.drawable.pic_2, R.drawable.pic_3,
R.drawable.pic_4, R.drawable.pic_5, R.drawable.pic_6,
R.drawable.pic_7, R.drawable.pic_8, R.drawable.pic_9,
R.drawable.pic_10, R.drawable.pic_11, R.drawable.pic_12,
R.drawable.pic_13, R.drawable.pic_14, R.drawable.pic_15,
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_vertical);
initData();
initView();
}
// 初始化数据,将数据添加到列表中
private void initData() {
for(int i=0; inew YYPicture(data[i]);
picList.add(yypic);
}
}
private void initView() {
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.vertical_recycler_view);
// 指定RecyclerView的布局方式
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
// 设置布局的排列方向,默认是纵向排列
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
// 加载数据,完成适配器设置
PictureAdapter adapter = new PictureAdapter(picList);
recyclerView.setAdapter(adapter);
}
}
YYPicture类实现YYPicture.java
public class YYPicture {
// 资源ID
private int picId;
public YYPicture(int id){
this.picId = id;
}
public int getPicID() {
return picId;
}
}
PictureAdapter适配器实现PictureAdapter.java
public class PictureAdapter extends RecyclerView.Adapter<PictureAdapter.ViewHolder> {
private List yyPictureList;
public PictureAdapter(List pictureList){
yyPictureList = pictureList;
}
static class ViewHolder extends RecyclerView.ViewHolder {
ImageView imageView;
public ViewHolder(View itemView) {
super(itemView);
imageView = (ImageView)itemView.findViewById(R.id.imageView);
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// 加载子项布局
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.picture_item, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
YYPicture yyPicture = yyPictureList.get(position);
holder.imageView.setImageResource(yyPicture.getPicID());
}
@Override
public int getItemCount() {
return yyPictureList.size();
}
}
picture_item.xml 是加载到RecyclerView子项的布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
LinearLayout>
从上诉代码中可以看出,最主要的实现还是在adapter上。
首先新建一个PictureAdapter类,继承RecyclerView.Adapter,并将泛型指定为PictureAdapter.ViewHolder。ViewHolder为PictureAdapter中定义的一个内部类。
ViewHolder内部类,继承RecyclerView.ViewHolder。ViewHolder的构造函数中要传入一个View参数。通常这个参数就是RecyclerView子项的最外层布局,然后通过这个参数,我们就可以通过findViewById()方法来获取到布局中的id。
PictureAdapter构造函数,这个方法主要用于将数据源传入,并将它赋值给全局变量yyPictureList ,后续就可以通过yyPictureList 操作数据了。
由于PictureAdapter是继承RecyclerView.Adapter的,那么就必须重写onCreateViewHolder()和onBindViewHolder()以及getItemCount()这3个方法。
onCreateViewHolder()方法,用于创建ViewHolder实例,并将加载的布局传入ViewHolder构造函数中,最后将ViewHolder的实例返回。
onBindViewHolder()方法,用于对RecyclerView子项的数据进行赋值,当子项数据被滚动到屏幕内是调用。
getItemCount()方法,用于返回数据源的长度。
二、RecyclerView的横向滚动(水平排列)
还记得指定RecyclerView的布局方式吗?嘿嘿。。。。
要想实现横向滚动的效果,只需要将RecyclerView布局设置为水平排列就行了。
// 指定RecyclerView的布局方式
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
// 设置布局的排列方向,默认是纵向排列
// layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
// 设置布局为水平排列
layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
recyclerView.setLayoutManager(layoutManager);
即,改成layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);就可以咯。
这里就不在写HorizontalActivity的实现了。。。
不管是修改主界面布局(activity_vertical.xml)还是修改加载到RecyclerView子项的布局文件(picture_item.xml )的orientation属性,都是不能改变RecyclerView的排列方式。
只能通过LinearLayoutManager的setOrientation()方法来设置排列方向。
三、RecyclerView的网格布局 – GridLayoutManager
同样的,只需要将RecyclerView布局方式修改成GridLayoutManager 即可。
这里就不在写HorizontalActivity的实现了。。。
修改如下:
// 指定RecyclerView的布局方式:线性布局
//LinearLayoutManager layoutManager = new LinearLayoutManager(this);
// 设置布局的排列方向,默认是纵向排列
// layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
// 设置布局为水平排列
// layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
// 指定RecyclerView的布局方式:网格布局
GridLayoutManager layoutManager = new GridLayoutManager(this,3);
recyclerView.setLayoutManager(layoutManager);
四、RecyclerView的交错网格布局(也叫瀑布流布局) – StaggeredGridLayoutManager
同样的,只需要将RecyclerView布局方式修改成StaggeredGridLayoutManager
即可。
修改如下:
// 指定RecyclerView的布局方式:线性布局
// LinearLayoutManager layoutManager = new LinearLayoutManager(this);
// 设置布局的排列方向,默认是纵向排列
// layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
// 设置布局为水平排列
// layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
// 指定RecyclerView的布局方式:网格布局
// GridLayoutManager layoutManager = new GridLayoutManager(this,3);
// 指定RecyclerView的布局方式:交错网格布局(瀑布流式布局)
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
只不过如果图片大小都一样的话,那看起来就跟网格布局一样了。所以可以通过修改图片大小打乱排序,即可程序效果。
五、RecyclerView的点击事件
RecyclerView并没有像ListView一样,有提供setOnItemClickListener()这样的注册监听器方法,它需要由用户自己为子项中具体的View注册点击事件。这样的话,它就可以轻松的实现子项中任意控件或者布局的点击事件。
holder.imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position = holder.getAdapterPosition();
YYPicture yyPicture = yyPictureList.get(position);
Toast.makeText(view.getContext(), "2222222", Toast.LENGTH_SHORT).show();
}
});