RecyclerView 将所有的显示规则交给一个叫 LayoutManager 的类去完成了。LayoutManager 是一个抽象类,系统已经为我们提供了三个默认的实现类,分别是 LinearLayoutManager 、 GridLayoutManager 、 StaggeredGridLayoutManager,从名字我们就能看出来了,分别是,线性显示、网格显示、瀑布流显示。
Recycle view和Listviet、GridView类似,都是可以显示同一种类型的View的集合控件。
首先看最简单的用法:
1.在build.gradle文件中加入
compile 'com.android.support:recyclerview-v7:24.0.0'
2.创建对象
RecyclerView rv_main_activity = (RecyclerView) findViewById(R.id.rv_main_activity);
3.设置显示规则,这里是用线性显示
rv_main_activity.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
4.设置适配器
rv_main_activity.setAdapter(linearLayoutAdapter);
适配器是用来这是每个item显示内容的。通常,我们写Listview的适配器的时候是先继承BaseAdapter,实现四个抽象方法,创建一个静态的Viewholder。
而Recycleview也是类似的步骤,首先继承RecycleView.Adapter类,实现3个抽象方法,创建一个静态的ViewHolder,继承Recycleview.ViewHolder 类。
下面直接上代码:
/**
* 作者:sufferable 17/2/10 14:24
* 邮箱:xsxdg666@gmail.com
*/
public class LinearLayoutAdapter extends RecyclerView.Adapter<LinearLayoutAdapter.MyHolder> {
private ArrayList<String> mList;
private Context mContext;
public LinearLayoutAdapter(ArrayList<String> list, Context context) {
mList = list;
mContext = context;
}
@Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = null;
RecyclerView.ViewHolder holder = null;
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
view = View.inflate(mContext, R.layout.item_linearlayout, null);
view.setLayoutParams(layoutParams);
return new MyHolder(view);
}
@Override
public void onBindViewHolder(MyHolder holder, final int position) {
holder.tv_item.setText(mList.get(position));
holder.tv_item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mOnRecyclerViewItemClickListener != null) {
mOnRecyclerViewItemClickListener.onItemClickListener(view, position);
}
}
});
}
//返回item的条数
@Override
public int getItemCount() {
return mList.size();
}
public class MyHolder extends RecyclerView.ViewHolder {
TextView tv_item;
public MyHolder(View itemView) {
super(itemView);
tv_item = (TextView) itemView.findViewById(R.id.tv_item_left);
}
}
private OnRecyclerViewItemClickListener mOnRecyclerViewItemClickListener;
public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener recyclerViewItemClickListener) {
this.mOnRecyclerViewItemClickListener = recyclerViewItemClickListener;
}
public interface OnRecyclerViewItemClickListener {
void onItemClickListener(View View, int positon);
}
}
因为Recycleview没有OnItemClickListener方法,所以点击事件可以直接写在Adapter里面,也可以像我上面代码写的那样,把点击事件做成接口暴露出去:
linearLayoutAdapter.setOnRecyclerViewItemClickListener(mOnRecyclerViewItemClickListener);
LinearLayoutAdapter.OnRecyclerViewItemClickListener mOnRecyclerViewItemClickListener = new LinearLayoutAdapter.OnRecyclerViewItemClickListener() {
@Override
public void onItemClickListener(View View, int positon) {
Intent intent = new Intent();
if (positon == 0){
intent.setClass(mContext,HeaderFooterActivity.class);
startActivity(intent);
}else if (positon == 1){
intent.setClass(mContext,DividerActivity.class);
startActivity(intent);
}else if (positon == 2){
intent.setClass(mContext,ManylayoutActivity.class);
startActivity(intent);
}else if (positon == 3){
intent.setClass(mContext,GridLayoutActivity.class);
startActivity(intent);
}else if (positon ==4){
intent.setClass(mContext,StaggeredGridLayoutActivity.class);
startActivity(intent);
}
}
};
加载数据、点击事件好了,运行起来发现没有分割线,恩简单,在XML文件中设置就好了还能同时设置divider的高度
android:divider=”@android:color/black”
android:dividerHeight=”2dp”
为什么没效果呢?因为在Recycleview中,要实现设置分割线的颜色和高度要麻烦一点,需要自己继承RecycleView.ItemDecoration来实现想要实现的方法
我在网上找了一个开源的应该能满足大部分情况的需求:
Divider.java 用 demo 可以查看:Github 【自定义 Divider 使用】
在使用Listview的时候大家经常使用addHeader和addFooter方法,但是发现recycle view没有这两个方法,因为在Recycleview中没有这两个概念,Recycleview是创建多个Viewholder加载多套布局的,不过如果是像我这样懒的人用习 惯了这两个方法,下面就是我封装的adapter,其实原理就是如果position == 0 或者等于list的长度就加载对应的布局,我只是做了一个封装,下面上代码:
/**
* 作者:sufferable 17/2/10 16:04
* 邮箱:xsxdg666@gmail.com
*/
public class HeaderFooterAdapter extends RecyclerView.Adapter<HeaderFooterAdapter.MyHolder> {
private Context mContext;
private ArrayList mList;
private RecyclerView mRecyclerView;
//用来判断是头布局还是列表还是尾布局
private int TYPE_NORMAL = 1000;
private int TYPE_HEADER = 1001;
private int TYPE_FOOTER = 1002;
private View VIEW_FOOTER;
private View VIEW_HEADER;
public HeaderFooterAdapter(Context context, ArrayList list) {
mContext = context;
mList = list;
}
@Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_FOOTER) {
//尾巴
return new MyHolder(VIEW_FOOTER);
} else if (viewType == TYPE_HEADER) {
//头
return new MyHolder(VIEW_HEADER);
} else {
//列表
return new MyHolder(getLayout(R.layout.item_linearlayout));
}
}
@Override
public void onBindViewHolder(MyHolder holder, int position) {
if (!isHeaderView(position) && !isFooterView(position)) {
if (headerView()) position--;
holder.mTextView_right.setText(mList.get(position) + "");
holder.mTextView_left.setText("列表");
}
}
@Override
public int getItemCount() {
int count = (mList == null ? 0 : mList.size());
if (VIEW_FOOTER != null) {
count++;
}
if (VIEW_HEADER != null) {
count++;
}
return count;
}
@Override
public int getItemViewType(int position) {
if (isHeaderView(position)) {
return TYPE_HEADER;
} else if (isFooterView(position)) {
return TYPE_FOOTER;
} else {
return TYPE_NORMAL;
}
}
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
try {
if (mRecyclerView == null && mRecyclerView != recyclerView) {
mRecyclerView = recyclerView;
}
ifGridLayoutManager();
} catch (Exception e) {
e.printStackTrace();
}
}
public void addHeaderView(View headerView) {
if (headerView()) {
throw new IllegalStateException("hearview has already exists!");
} else {
//避免出现宽度自适应
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
headerView.setLayoutParams(params);
VIEW_HEADER = headerView;
ifGridLayoutManager();
notifyItemInserted(0);
}
}
public void addFooterView(View footerView) {
if (footerView()) {
throw new IllegalStateException("footerView has already exists!");
} else {
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
footerView.setLayoutParams(params);
VIEW_FOOTER = footerView;
ifGridLayoutManager();
notifyItemInserted(getItemCount() - 1);
}
}
private void ifGridLayoutManager() {
if (mRecyclerView == null) return;
final RecyclerView.LayoutManager layoutManager = mRecyclerView.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
final GridLayoutManager.SpanSizeLookup originalSpanSizeLookup =
((GridLayoutManager) layoutManager).getSpanSizeLookup();
((GridLayoutManager) layoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return (isHeaderView(position) || isFooterView(position)) ?
((GridLayoutManager) layoutManager).getSpanCount() :
1;
}
});
}
}
private View getLayout(int layoutId) {
return LayoutInflater.from(mContext).inflate(layoutId, null);
}
private boolean headerView() {
return VIEW_HEADER != null;
}
private boolean isHeaderView(int position) {
return headerView() && position == 0;
}
private boolean isFooterView(int position) {
return footerView() && position == getItemCount() - 1;
}
public boolean footerView() {
return VIEW_FOOTER != null;
}
public static class MyHolder extends RecyclerView.ViewHolder{
TextView mTextView_left;
TextView mTextView_right;
public MyHolder(View itemView) {
super(itemView);
mTextView_left = (TextView) itemView.findViewById(R.id.tv_item_left);
mTextView_right = (TextView) itemView.findViewById(R.id.tv_item_rigtht);
}
}
}
使用的时候:
RecyclerView rv_main_activity = (RecyclerView) findViewById(R.id.rv_main_activity);
rv_main_activity.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
HeaderFooterAdapter headerFooterAdapter = new HeaderFooterAdapter(mContext, list);
rv_main_activity.setAdapter(headerFooterAdapter);
View footInflate = LayoutInflater.from(this).inflate(R.layout.item_footer, null);
View HeaderInflate = LayoutInflater.from(this).inflate(R.layout.item_header, null);
headerFooterAdapter.addFooterView(footInflate);
headerFooterAdapter.addHeaderView(HeaderInflate);
然后下面的就跟listview的头布局尾布局一样使用了。既然写了这个就顺便把Recycleview加载多套布局的代码也发出来吧:
/**
* 作者:sufferable 17/2/10 17:21
* 邮箱:xsxdg666@gmail.com
*/
public class ManylayoutAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private final int TEMP_1 = 1000;
private final int TEMP_2 = 1001;
private final int TEMP_3 = 1002;
private final int TEMP_4 = 1003;
private ArrayList mList;
private Context mContext;
public ManylayoutAdapter(ArrayList list, Context context) {
mList = list;
mContext = context;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = null;
RecyclerView.ViewHolder holder = null;
LinearLayout.LayoutParams layoutParams =new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,LinearLayout.LayoutParams.WRAP_CONTENT);
switch (viewType){
case TEMP_1:
view = View.inflate(mContext,R.layout.item_one,null);
view.setLayoutParams(layoutParams);
holder = new VH1(view);
return holder;
case TEMP_2:
view = View.inflate(mContext,R.layout.item_two,null);
view.setLayoutParams(layoutParams);
holder = new VH2(view);
return holder;
case TEMP_3:
view = View.inflate(mContext,R.layout.item_three,null);
view.setLayoutParams(layoutParams);
holder = new VH3(view);
return holder;
default:
view = View.inflate(mContext,R.layout.item_linearlayout,null);
view.setLayoutParams(layoutParams);
holder = new VH4(view);
return holder;
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (getItemViewType(position)){
case TEMP_1:
VH1 vh1 = (VH1) holder;
vh1.mTextView.setText("第一种布局");
break;
case TEMP_2:
VH2 vh2 = (VH2) holder;
//设置数据
vh2.image.setImageResource(R.drawable.item_1);
break;
case TEMP_3:
VH3 vh3 = (VH3) holder;
vh3.mTextView.setText("第三种布局");
break;
default:
VH4 vh4 = (VH4) holder;
vh4.mTextView_left.setText("左边");
vh4.mTextView_reght.setText("右边");
break;
}
}
@Override
public int getItemViewType(int position) {
if (position >= 0 && position < 10) {
return TEMP_1;
} else if (position >= 10 && position < 20) {
return TEMP_2;
} else if (position >= 20 && position < 30) {
return TEMP_3;
} else {
return TEMP_4;
}
}
@Override
public int getItemCount() {
return mList.size();
}
public static class VH1 extends RecyclerView.ViewHolder {
TextView mTextView;
public VH1(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.text);
}
}
public static class VH2 extends RecyclerView.ViewHolder {
ImageView image;
public VH2(View itemView) {
super(itemView);
image = (ImageView) itemView.findViewById(R.id.image);
}
}
public static class VH3 extends RecyclerView.ViewHolder {
TextView mTextView;
ImageView mImageView;
public VH3(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.text);
mImageView = (ImageView) itemView.findViewById(R.id.image);
}
}
public static class VH4 extends RecyclerView.ViewHolder {
TextView mTextView_reght;
TextView mTextView_left;
public VH4(View itemView) {
super(itemView);
mTextView_reght = (TextView) itemView.findViewById(R.id.tv_item_rigtht);
mTextView_left = (TextView) itemView.findViewById(R.id.tv_item_left);
}
}
}