RecyclerView是androi 5.x提供的新组件,是ListView 的升级版,比ListView更灵活,更先进。具体表现这几个方面:
- 把ViewHolder的实现封装起来,规范了ViewHolder,把item的view写入ViewHolder中,通过复用ViewHolder来实现view的复用。
- RecyclerView.Adapter中把view的回收和内容改变等操作分开解耦了,比传统的Adapter更为灵活。
- 独立的LayoutManager,可以灵活的控制RecyclerView中items的布局,目前SDK中提供了三种LayoutManager对象:LinearLayoutManager(垂直布局、水平布局)、GridLayoutManager(网格布局)、StaggeredGridLayoutManager(瀑布流布局);
- 提供了RecyclerView.ItemAnimator可以设置items增加、删除时的动画(默认已有定义了动画);
使用RecycleView
1、添加依赖
需要在android studio的build.gradle中添加依赖,
dependencies {
...
compile 'com.android.support:recyclerview-v7:23.2.0'
}
2、布局中使用RecyclerView控件
添加完依赖后,在布局中添加RecyclerView控件,使用方法和ListView相似
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RadioGroup
android:id="@+id/rg_selectDisplayMethod"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:checked="true"
android:id="@+id/rb_linear_horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="线性横向排列" />
<RadioButton
android:id="@+id/rb_linear_vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="线性纵向排列" />
<RadioButton
android:id="@+id/rb_grid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="网格排列" />
<RadioButton
android:id="@+id/rb_staggeredGridL"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="瀑布流排列" />
</RadioGroup>
<Button
android:id="@+id/btn_addItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:text="Add" />
<Button
android:id="@+id/btn_deleteItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="20dp"
android:layout_marginTop="60dp"
android:text="Delete" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_myRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/rg_selectDisplayMethod" />
</RelativeLayout>
接着创建RecyclerView需要的item对象布局,
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="@+id/tv_show_text"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_margin="10dp"
android:gravity="center"
android:background="@color/colorPrimary"
android:layout_height="wrap_content" />
3、编写adapter对象
编写RecyclerView需要的adapter,需要继承RecyclerView.Adapter,不同于传统的Adapter,它没有getView方法,取而代之的是onCreateViewHolder和onBindViewHolder,把view的复用和数据的绑定解耦。
RecyclerView.Adapter主要提供的3中方法:
- getItemCount 获取总的条目数
- onCreateViewHolder 创建ViewHolder
- onBindViewHolder 将数据绑定至ViewHolder
RecyclerView并没有提供item的点击事件,因此我们需要自己定义点击事件,Adapter是添加点击事件的好地方,里面是构造布局等View的主要场所,也是数据和布局进行绑定的地方。
首先定义接口对象
private OnItemClickListener mItemClickListener = null;
public void setOnItemClickListener(OnItemClickListener listener) {
mItemClickListener = listener;
}
public interface OnItemClickListener {
void onItemClick(View v, int position);
}
OnItemClickListener 通常在ViewHolder中触发,ViewHolder对象传入的View对象相当于BaseAdapter中getView方法的convertView,使用如下:
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView mShowText;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
mShowText = (TextView)itemView;
}
@Override
public void onClick(View v) {
if (mItemClickListener !=null){
mItemClickListener.onItemClick(v,getPosition());
}
}
}
RecyclerAdapter 的完整代码如下:
package com.cyf.recycleviewdemo;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.ViewHolder> {
private List<DataBean> mDataBean;
private LayoutInflater mLayoutInflater;
public RecyclerAdapter(List<DataBean> data, Context ct) {
mDataBean = data;
mLayoutInflater = LayoutInflater.from(ct);
}
@Override
public RecyclerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mLayoutInflater.inflate(R.layout.recycler_item, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerAdapter.ViewHolder holder, int position) {
ViewGroup.LayoutParams lp = holder.mShowText.getLayoutParams();
lp.height = mDataBean.get(position).getTextViewHeight();
lp.width = mDataBean.get(position).getTextViewWidth();
holder.mShowText.setLayoutParams(lp);
holder.mShowText.setText(mDataBean.get(position).getText()+" "+position);
}
@Override
public int getItemCount() {
return mDataBean.size();
}
private OnItemClickListener mItemClickListener = null;
public void setOnItemClickListener(OnItemClickListener listener) {
mItemClickListener = listener;
}
public interface OnItemClickListener {
void onItemClick(View v, int position);
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView mShowText;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
mShowText = (TextView)itemView;
}
@Override
public void onClick(View v) {
if (mItemClickListener !=null){
mItemClickListener.onItemClick(v,getPosition());
}
}
}
}
4、编写MainActivity
需要声明LayoutManager,LayoutManager决定了布局的排列方法;
线性布局
在线性布局中,有线性横向排列,又有线性纵向排列,其中,数据的显示又有正反2种排列显示方式。
/**
* @param context Current context, will be used to access resources.
* @param orientation Layout orientation. Should be {@link #HORIZONTAL} or {@link
* #VERTICAL}.(线性横向排列,线性纵向排列)
* @param reverseLayout When set to true, layouts from end to start.(true:反向排列,false:正向排列)
*/
public LinearLayoutManager(Context context, int orientation, boolean reverseLayout)
Grid布局(网格布局)
如果想要一个Grid布局的列表,只要声明LayoutManager为GridLayoutManager即可
mLayoutManager = new GridLayoutManager(context,columNum);
mRecyclerView.setLayoutManager(mLayoutManager);
在Grid布局中也可以设置列表的Orientation属性,来实现横向和纵向的Grid布局
瀑布流布局
瀑布流使用StaggeredGridLayoutManager对象,其中有瀑布流的方法(横/纵向),还有流面显示数量
/**
* Creates a StaggeredGridLayoutManager with given parameters.
*
* @param spanCount If orientation is vertical, spanCount is number of columns. If
* orientation is horizontal, spanCount is number of rows.
* @param orientation {@link #VERTICAL} or {@link #HORIZONTAL}
*/
public StaggeredGridLayoutManager(int spanCount, int orientation)
部分MainActivity代码如下
mRecyclerView = (RecyclerView) findViewById(R.id.rv_myRecyclerView);
//创建并设置Adapter
mAdapter = new RecyclerAdapter(mDatas, this);
mRecyclerView.setAdapter(mAdapter);
//创建默认的横向线性排列LayoutManager
mLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
mRecyclerView.setLayoutManager(mLayoutManager);
//如果可以确定每个item的高度是固定的,设置这个选项可以提高性能
mRecyclerView.setHasFixedSize(true);