RecyclerView 是Android L版本中新添加的一个用来取代ListView、GridView的SDK,它的灵活性与可替代性比listview更好。接下来通过一系列的文章讲解如何使用RecyclerView,彻底抛弃ListView.了解RecyclerView架构,可以高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator可以实现的想要的效果。
1、首先介绍几种LayoutManager
目前SDK中提供了三种自带的LayoutManager:
LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager
LinearLayoutManager mManager = new LinearLayoutManager(mContent);
LinearLayoutManager mManager = new LinearLayoutManager(mContent, LinearLayoutManager.VERTICAL, false);//垂直布局,true表示左右翻转数据从后往前显示,false不翻转 数据从0往后显示。
GridLayoutManager mManager = new GridLayoutManager(mContent,3);
GridLayoutManager mManager = new GridLayoutManager(mContent,3,LinearLayoutManager.HORIZONTAL,false);//每行3列,水平,true表示左右翻转,false不翻转
mRecyclerView.setLayoutManager(mManager);
//设置瀑布流效果
recyclerview.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
2、RecycleView简单使用
//初始化控件
mRecyclerView = findView(R.id.id_recyclerview);
//设置布局管理器
mManager = new LinearLayoutManager(mContent);
mRecyclerView.setLayoutManager(mManager);
//设置adapter
mRecyclerView.setAdapter(mAdapter)
//设置Item增加、移除动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割线
mRecyclerView.addItemDecoration(new DividerItemDecoration(
getActivity(), DividerItemDecoration.HORIZONTAL_LIST));
3、接下来介绍的就是RecyclerView的适配器了,同样,RecyclerView和ListView,GridView一样需要adapter来填充数据,同样,自定义一个adapter需要继承RecyclerView.Adapter,代码需要实现几个父类方法onCreateViewHolder,onBindViewHolder,getItemCount(),根据名字就能知道:
(1)onCreateViewHolder:主要返回的是拿到布局,进而返回ViewHolder
return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_cell,null));
(2)onBindViewHolder:拿到ViewHolder中的控件对其赋值操作
(3)getItemCount():返回数组的size()
使用前必须先添加依赖包
在AS的build.gradle中添加依赖,然后同步一下就可以引入依赖包:
dependencies {
compile 'com.android.support:recyclerview-v7:25.3.1'
}
下面是今天主要记录的内容,那就是封装万能的RecyclerView的适配器。
BaseRecyclerAdapter适配器类:
package com.recyclerview;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
/**
* 作者:willkong on 2017/7/20.
* QQ号:547860818
* 作用:万能的RecyclerView适配器
*/
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseRecyclerHolder> {
private Context context;//上下文
private List<T> list;//数据源
private LayoutInflater inflater;//布局器
private int itemLayoutId;//布局id
private boolean isScrolling;//是否在滚动
private OnItemClickListener listener;//点击事件监听器
private OnItemLongClickListener longClickListener;//长按监听器
private RecyclerView recyclerView;
//在RecyclerView提供数据的时候调用
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
this.recyclerView = recyclerView;
}
@Override
public void onDetachedFromRecyclerView(RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
this.recyclerView = null;
}
/**
* 定义一个点击事件接口回调
*/
public interface OnItemClickListener {
void onItemClick(RecyclerView parent, View view, int position);
}
public interface OnItemLongClickListener {
boolean onItemLongClick(RecyclerView parent, View view, int position);
}
/**
* 插入一项
*
* @param item
* @param position
*/
public void insert(T item, int position) {
list.add(position, item);
notifyItemInserted(position);
}
/**
* 删除一项
*
* @param position 删除位置
*/
public void delete(int position) {
list.remove(position);
notifyItemRemoved(position);
}
public BaseRecyclerAdapter(Context context, List<T> list, int itemLayoutId,RecyclerView recyclerView) {
this.context = context;
this.list = list;
this.itemLayoutId = itemLayoutId;
this.recyclerView = recyclerView;
inflater = LayoutInflater.from(context);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
isScrolling = !(newState == RecyclerView.SCROLL_STATE_IDLE);
if (!isScrolling) {
notifyDataSetChanged();
}
}
});
}
@Override
public BaseRecyclerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = inflater.inflate(itemLayoutId, parent, false);
return BaseRecyclerHolder.getRecyclerHolder(context, view);
}
@Override
public void onBindViewHolder(final BaseRecyclerHolder holder, int position) {
//点击背景
if (listener != null) {
holder.itemView.setBackgroundResource(R.drawable.recycler_bg);//设置背景
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null && view != null && recyclerView != null) {
int position = recyclerView.getChildAdapterPosition(view);
listener.onItemClick(recyclerView, view, position);
}
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if (longClickListener != null && view != null && recyclerView != null) {
int position = recyclerView.getChildAdapterPosition(view);
longClickListener.onItemLongClick(recyclerView, view, position);
return true;
}
return false;
}
});
convert(holder, list.get(position), position, isScrolling);
}
@Override
public int getItemCount() {
return list == null ? 0 : list.size();
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.listener = listener;
}
public void setOnItemLongClickListener(OnItemLongClickListener longClickListener) {
this.longClickListener = longClickListener;
}
/**
* 填充RecyclerView适配器的方法,子类需要重写
*
* @param holder ViewHolder
* @param item 子项
* @param position 位置
* @param isScrolling 是否在滑动
*/
public abstract void convert(BaseRecyclerHolder holder, T item, int position, boolean isScrolling);
}
对应的ViewHolder类BaseRecyclerHolder:
package com.recyclerview;
import android.content.Context;
import android.graphics.Bitmap;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
/**
* 作者:willkong on 2017/7/20.
* QQ号:547860818
* 作用:万能的RecyclerView的ViewHolder
*/
public class BaseRecyclerHolder extends RecyclerView.ViewHolder {
private SparseArray<View> views;
private Context context;
private BaseRecyclerHolder(Context context, View itemView) {
super(itemView);
this.context = context;
//指定一个初始为8
views = new SparseArray<>(8);
}
/**
* 取得一个RecyclerHolder对象
*
* @param context 上下文
* @param itemView 子项
* @return 返回一个RecyclerHolder对象
*/
public static BaseRecyclerHolder getRecyclerHolder(Context context, View itemView) {
return new BaseRecyclerHolder(context, itemView);
}
public SparseArray<View> getViews() {
return this.views;
}
/**
* 通过view的id获取对应的控件,如果没有则加入views中
*
* @param viewId 控件的id
* @return 返回一个控件
*/
@SuppressWarnings("unchecked")
public <T extends View> T getView(int viewId) {
View view = views.get(viewId);
if (view == null) {
view = itemView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
}
/**
* 设置字符串
*/
public BaseRecyclerHolder setText(int viewId, String text) {
TextView tv = getView(viewId);
tv.setText(text);
return this;
}
/**
* 设置图片
*/
public BaseRecyclerHolder setImageResource(int viewId, int drawableId) {
ImageView iv = getView(viewId);
iv.setImageResource(drawableId);
return this;
}
/**
* 设置图片
*/
public BaseRecyclerHolder setImageBitmap(int viewId, Bitmap bitmap) {
ImageView iv = getView(viewId);
iv.setImageBitmap(bitmap);
return this;
}
// /**
// * 设置图片
// */
// public BaseRecyclerHolder setImageByUrl(int viewId,String url){
// Picasso.with(context).load(url).into((ImageView) getView(viewId));
// // ImageLoader.getInstance().init(ImageLoaderConfiguration.createDefault(context));
// // ImageLoader.getInstance().displayImage(url, (ImageView) getView(viewId));
// return this;
// }
}
分割线类DividerListItemDecoration:
package com.recyclerview;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class DividerListItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
private Drawable mDivider;
private int mOrientation;
public DividerListItemDecoration(Context context, int orientation) {
final TypedArray a = context.obtainStyledAttributes(ATTRS);
mDivider = a.getDrawable(0);
a.recycle();
setOrientation(orientation);
}
public void setOrientation(int orientation) {
if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
throw new IllegalArgumentException("invalid orientation");
}
mOrientation = orientation;
}
@Override
public void onDraw(Canvas c, RecyclerView parent) {
// Log.e("recyclerview - itemdecoration", "onDraw()");
if (mOrientation == VERTICAL_LIST) {
drawVertical(c, parent);
} else {
drawHorizontal(c, parent);
}
}
public void drawVertical(Canvas c, RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
public void drawHorizontal(Canvas c, RecyclerView parent) {
final int top = parent.getPaddingTop();
final int bottom = parent.getHeight() - parent.getPaddingBottom();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int left = child.getRight() + params.rightMargin;
final int right = left + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
@Override
public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
if (mOrientation == VERTICAL_LIST) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else {
outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
}
}
}
点击阴影recycler_bg:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
<shape android:shape="rectangle">
<solid android:color="#cfd8dc"/>
</shape>
</item>
</selector>
使用实例:
package com.recyclerview;
import android.app.Activity;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.ArrayList;
import static android.R.attr.data;
public class MainActivity extends Activity implements View.OnClickListener {
private Button btn_add;
private Button btn_delete;
private Button btn_list;
private Button btn_grid;
private Button btn_flow;
private RecyclerView recyclerview;
private ArrayList<String> datas;
// private MyRecyclerViewAdapter adapter;
private BaseRecyclerAdapter adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
adapter = new BaseRecyclerAdapter<String>(MainActivity.this, datas, R.layout.item_recyclerview,recyclerview) {
@Override
public void convert(BaseRecyclerHolder holder, String item, int position, boolean isScrolling) {
holder.setText(R.id.tv_title,item);
}
};
recyclerview.setAdapter(adapter);
recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this,LinearLayoutManager.VERTICAL,false));
recyclerview.addItemDecoration(new DividerListItemDecoration(MainActivity.this,DividerListItemDecoration.VERTICAL_LIST));
adapter.setOnItemClickListener(new BaseRecyclerAdapter.OnItemClickListener() {
@Override
public void onItemClick(RecyclerView parent, View view, int position) {
Toast.makeText(MainActivity.this,"data="+datas.get(position),Toast.LENGTH_SHORT).show();
}
});
// //设置recyclerview适配器
// adapter = new MyRecyclerViewAdapter(MainActivity.this,datas);
// recyclerview.setAdapter(adapter);
// //LayoutManager
// recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this,LinearLayoutManager.VERTICAL,false));
recyclerview.scrollToPosition(datas.size()-1);
// //添加RecyclerView的分割线
// recyclerview.addItemDecoration(new DividerListItemDecoration(MainActivity.this,DividerListItemDecoration.VERTICAL_LIST));
//
// //设置点击某条的监听
// adapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
// @Override
// public void onItemClick(View view, String data) {
// Toast.makeText(MainActivity.this,"data="+data,Toast.LENGTH_SHORT).show();
// }
// });
// //设置动画
// recyclerview.setItemAnimator(new DefaultItemAnimator());
}
private void initView() {
btn_add = (Button) findViewById(R.id.btn_add);
btn_delete = (Button) findViewById(R.id.btn_delete);
btn_list = (Button) findViewById(R.id.btn_list);
btn_grid = (Button) findViewById(R.id.btn_grid);
btn_flow = (Button) findViewById(R.id.btn_flow);
recyclerview = (RecyclerView) findViewById(R.id.recyclerview);
//设置点击事件
btn_add.setOnClickListener(this);
btn_delete.setOnClickListener(this);
btn_list.setOnClickListener(this);
btn_grid.setOnClickListener(this);
btn_flow.setOnClickListener(this);
}
private void initData() {
//准备数据集合
datas = new ArrayList<>();
for (int i=0;i<100;i++){
datas.add("Content_"+i);
}
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_add:
// adapter.addData(0,"New_Content");
adapter.insert("New_Content",0);
recyclerview.scrollToPosition(0);
break;
case R.id.btn_delete:
// adapter.removeData(0);
adapter.delete(0);
break;
case R.id.btn_list:
//设置List类型效果
recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this,LinearLayoutManager.VERTICAL,false));
break;
case R.id.btn_grid:
//设置Grid类型效果
recyclerview.setLayoutManager(new GridLayoutManager(MainActivity.this,2,GridLayoutManager.VERTICAL,true));
recyclerview.scrollToPosition(datas.size()-1);
break;
case R.id.btn_flow:
//设置瀑布流效果
recyclerview.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
break;
}
}
}
<?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"
android:orientation="vertical"
tools:context="com.recyclerview.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="添加"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="删除"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="List"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Grid"
android:textAllCaps="false" />
<Button
android:id="@+id/btn_flow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="flow"
android:textAllCaps="false" />
</LinearLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
item_recyclerview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:padding="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#22000000"
android:orientation="horizontal">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ico_jiechu" />
<TextView
android:id="@+id/tv_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="3dp"
android:text="Content"
android:textAllCaps="false"
android:textColor="#000000" />
</LinearLayout>
</RelativeLayout>