转载请标明原文地址:http://blog.csdn.net/yalinfendou/article/details/46636409【yalinfendou的博客】
Android RecyclerView 在去年的Google I/O大会上就推出来了,以前经常使用的ListView 继承的是AbsListView,而RecyclerView则直接继承 ViewGroup,并实现了ScrollingView 和 NestedScrollingChild接口,RecyclerView相比ListView,是一次彻底的改变,RecyclerView 比ListView更加强大灵活。
如果想水平排列显示,把layoutManager.setOrientation(LinearLayoutManager.VERTICAL)替换成layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL)即可。
// 如果布局大小一致有利于优化
recyclerView.setHasFixedSize(true);
// 创建一个线性布局管理器
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
// 设置布局管理器
recyclerView.setLayoutManager(layoutManager);
// 创建数据集
List listData = new ArrayList();
for (int i = 0; i < 20; ++i) {
User uBean = new User();
uBean.setUsername("我是Item" + i);
listData.add(uBean);
}
// 创建Adapter,并指定数据集
MyAdapter adapter = new MyAdapter(context, listData);
// 设置Adapter
recyclerView.setAdapter(adapter);
MyAdapter:public class MyAdapter extends RecyclerView.Adapter {
private Context context;
private List listData;
public MyAdapter(Context context, List mList) {
super();
this.context = context;
this.listData = mList;
}
@Override
public int getItemCount() {
// TODO Auto-generated method stub
return listData.size();
}
@Override
public MViewHolder onCreateViewHolder(ViewGroup viewGroup, int arg1) {
View view = View.inflate(viewGroup.getContext(),
R.layout.item_user_friend_nod, null);
// 创建一个ViewHolder
MViewHolder holder = new MViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(MViewHolder mViewHolder, int arg1) {
mViewHolder.mTextView.setText(listData.get(arg1).getUsername());
mViewHolder.image.setBackgroundResource(R.drawable.head);
}
public class MViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ImageView image;
public MViewHolder(View view) {
super(view);
this.mTextView = (TextView) view.findViewById(R.id.tv_friend_name);
this.image = (ImageView) itemView.findViewById(R.id.img_friend_avatar);
}
}
}
MViewHolder是一个内部类,在其构造函数中,获取控件。 MyAdapter继承了RecyclerView.Adapter/**
* item点击回调接口
*
* @author wen_er
*
*/
public interface ItemClickListener {
/**
* Item 普通点击
*/
public void onItemClick(View view, int postion);
/**
* Item 长按
*/
public void onItemLongClick(View view, int postion);
/**
* Item 内部View点击
*/
public void onItemSubViewClick(View view, int postion);
}
然后再稍稍改造一下MyAdapter:
public class MyAdapter extends RecyclerView.Adapter {
private Context context;
private List listData;
private ItemClickListener mItemClickListener;
public MyAdapter(Context context, List mList) {
super();
this.context = context;
this.listData = mList;
}
public void setItemClickListener(ItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
@Override
public int getItemCount() {
// TODO Auto-generated method stub
return listData.size();
}
@Override
public MViewHolder onCreateViewHolder(ViewGroup viewGroup, int arg1) {
View view = View.inflate(viewGroup.getContext(),
R.layout.item_user_friend_nod, null);
// 创建一个ViewHolder
MViewHolder holder = new MViewHolder(view);
return holder;
}
@Override
public void onBindViewHolder(final MViewHolder mViewHolder,
final int postion) {
mViewHolder.mTextView.setText(listData.get(postion).getUsername());
mViewHolder.image.setBackgroundResource(R.drawable.head);
// 为image添加监听回调
mViewHolder.image.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (null != mItemClickListener) {
mItemClickListener.onItemSubViewClick(mViewHolder.image,
postion);
}
}
});
}
public class MViewHolder extends RecyclerView.ViewHolder {
public TextView mTextView;
public ImageView image;
public MViewHolder(final View view) {
super(view);
this.mTextView = (TextView) view.findViewById(R.id.tv_friend_name);
this.image = (ImageView) itemView.findViewById(R.id.img_friend_avatar);
//为item添加普通点击回调
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (null != mItemClickListener) {
mItemClickListener.onItemClick(view, getPosition());
}
}
});
//为item添加长按回调
view.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (null != mItemClickListener) {
mItemClickListener.onItemLongClick(view, getPosition());
}
return true;
}
});
}
}
}
对比以上的代码,只是在onBindViewHolder中为Item的子View添加监听回调,在MViewHolder的构造方法中为Item添加点击和长按监听回调。
//为Item具体实例点击3种事件
adapter.setItemClickListener(new ItemClickListener() {
@Override
public void onItemSubViewClick(View view, int postion) {
T.showShort(context, "亲,你点击了Image"+postion);
}
@Override
public void onItemLongClick(View view, int postion) {
T.showShort(context, "亲,你长按了Item"+postion);
}
@Override
public void onItemClick(View view, int postion) {
T.showShort(context, "亲,你点击了Item"+postion);
}
});
addItemDecoration的参数ItemDecoration需要我们重写它的onDraw,onDrawOver和getItemOffsets方法,因为item可能是水平排列,也可能是垂直排列,所以我们传入一个参数oritation值,作为item排列方向的标记,参考了Git上的代码,原来的代码当水平布局时,分隔线的高度会填满整个屏幕(Item并未填满整个屏幕),所以稍稍做了改动。
public class ItemDecorationDivider extends ItemDecoration {
private Drawable mDivider;
private int mOritation;
public ItemDecorationDivider(Context context, int resId, int oritation) {
mDivider = context.getResources().getDrawable(resId);
this.mOritation = oritation;
Log.i("ItemDecorationDivider", "mOritation=" + mOritation);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent) {
if (mOritation == LinearLayoutManager.VERTICAL) {
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);
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);
}
} else if (mOritation == LinearLayoutManager.HORIZONTAL) {
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();
final int bottom = child.getBottom();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
@Override
public void getItemOffsets(Rect outRect, int position,
RecyclerView parent) {
if (mOritation == LinearLayoutManager.VERTICAL) {
outRect.set(0, 0, 0, mDivider.getIntrinsicWidth());
// outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
} else if (mOritation == LinearLayoutManager.HORIZONTAL) {
// outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
}
}
}
recyclerView.addItemDecoration(new ItemDecorationDivider(context,
R.drawable.item_divider, LinearLayoutManager.VERTICAL));
item_divider:
notifyItemChanged(int position)
//通知位置position的Item的数据改变
notifyItemInserted(int)//通知位置position的Item的数据插入
notifyItemRemoved(int)//通知位置position的Item的数据移除
notifyItemRangeChanged(int positionStart, int itemCount) //通知从位置positionStart开始,有itemCount个Item的数据发生改变
notifyItemRangeInserted(int positionStart, int itemCount) //通知从位置positionStart开始,有itemCount个Item的数据插入
notifyItemRangeRemoved(int positionStart, int itemCount)//通知从位置positionStart开始,有itemCount个Item的数据移除
/** * TODO<添加数据,指定其位置> */ public void addData(User info, int position) { listData.add(position, info); notifyItemInserted(position); // notifyDataSetChanged(); //不会触发Item的动画效果,告知数据改变,刷新UI } /** * TODO<添加数据到最后面添加> */ public void addData(User info) { // listData.add(position, info); // notifyItemInserted(position); listData.add(info); notifyDataSetChanged(); } /** * TODO<删除数据,指定其位置> */ public void daleteData(int position) { listData.remove(position); notifyItemRemoved(position); } /** * TODO<某一位置开始,有itemCount个Item的数据删除> */ public void itemRangeRemoved(int positionStart, int itemCount) { for (int i = positionStart; i < itemCount; i++) { listData.remove(positionStart); } notifyItemRangeRemoved(positionStart, itemCount); // notifyDataSetChanged(); //不会触发Item的动画效果,告知数据改变,刷新UI } /** * TODO<某一位置开始,有itemCount个Item的数据插入> */ public void itemRangeInserted(User info, int positionStart, int itemCount) { for (int i = positionStart; i < itemCount; i++) { listData.add(i, info); } notifyItemRangeInserted(positionStart, itemCount); // notifyDataSetChanged(); }
case R.id.btn3:
User uBean = new User();
uBean.setUsername("我是增加的Item");
adapter.addData(uBean, 0);// 添加到第一个
break;
case R.id.btn4:
adapter.daleteData(0); // 删除第一个
break;
case R.id.btn5:
User uBean1 = new User();
uBean1.setUsername("我是连续添加的Item");
adapter.itemRangeInserted(uBean1, 0, 5);
break;
case R.id.btn6:
adapter.itemRangeRemoved(0, 5);
break;
// 使用RecyclerView提供的默认的动画效果
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView,
int scrollState) {
updateState(scrollState);
}
@Override
public void onScrolled(RecyclerView recyclerView, int i, int i2) {
String s = "可见Item数量:" + layoutManager.getChildCount()+"\n"
+ "可见Item第一个Position:"
+ layoutManager.findFirstVisibleItemPosition()+"\n"
+ "可见Item最后一个Position:"
+ layoutManager.findLastVisibleItemPosition();
tv.setText(s);
}
});
private void updateState(int scrollState) {
String stateName = "Undefined";
switch (scrollState) {
case SCROLL_STATE_IDLE:
stateName = "Idle";
break;
case SCROLL_STATE_DRAGGING:
stateName = "Dragging";
break;
case SCROLL_STATE_SETTLING:
stateName = "Flinging";
break;
}
tv_state.setText("滑动状态:" + stateName);
}
当滚动RecyclerView的时候,效果如DEMO效果图所示。
gridLayoutManager = new GridLayoutManager(this, 3,
GridLayoutManager.VERTICAL, false);
// 设置布局管理器
recyclerView.setLayoutManager(gridLayoutManager);
StaggeredGridLayoutManager = new StaggeredGridLayoutManager(2,
StaggeredGridLayoutManager.VERTICAL);
// 设置布局管理器
recyclerView.setLayoutManager(StaggeredGridLayoutManager);