android常用控件RecyclerView(三) RecyclerView的使用
来源:互联网 发布:淘宝店中国制造 编辑:程序博客网 时间:2024/05/02 01:18
当我们需要对大量的数据进行展示的时候,通常会用到ListView、GridView等。而Recycler则可以看做是能够完成ListView、GridView、StaggeredGridView的一个强大容器。
先来看看RecyclerView的基本使用。
通常在使用ListView等控件的时候都需要一个数据适配器,在RecyclerView中也继承了这个优良的传统。
为了使RecyclerView将数据的样式展示成不同的样式,它为我们提供了LayoutManager用来控制数据展示的布局。通过设置ItemDecoration可以控制分分割线的样式,通过ItemAnimator可以控制增删数据时的动画效果。
一 Recycler基础使用
下面,先来一个ListView布局的列子。
public class MainActivity extends Activity { RecyclerView recyclerView; ArrayList<Product> productList; private StaggeredGridLayoutManager manager; MyNormalRecyclerAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); recyclerView= (RecyclerView) findViewById(R.id.recycler); //layoutManager recyclerView.setLayoutManager(new LinearLayoutManager(this)); initData(); //adapter adapter=new MyNormalRecyclerAdapter(productList); recyclerView.setAdapter(adapter); } private void initData() { productList = new ArrayList<Product>(); Product product; for (int i = 0; i < 30; i++) { int asd = R.drawable.ic_launcher; product = new Product(asd, "" + i); productList.add(product); } }}
在上面代码中,先初始化了一个数据源,之后通过 recyclerView.setLayoutManager(new LinearLayoutManager(this));将recyclerview的设置成ListView的显示样式。
这里使用了一个自定义的adapter。
public class MyRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>/*<RecyclerView.ViewHolder>*//*RecyclerView.Adapter*/{ public static final int TYPE_HEADER = 0; public static final int TYPE_NORMAL = 1; public static final int TYPE_FOOTER = 2; private View mHeaderView; private View mFooterView; ArrayList<Product> products; public int getItemViewType(int position) { Log.d("HK", "getItemViewType called "+position); if(mHeaderView == null) return TYPE_NORMAL; if(position == 0) return TYPE_HEADER; return TYPE_NORMAL; } public MyRecyclerAdapter(ArrayList<Product> list) { products = list; } @Override public int getItemCount() { return 0; } public int getRealPosition(RecyclerView.ViewHolder holder) { int position = holder.getLayoutPosition(); Log.d("HK", "getRealPosition called "+position); return mHeaderView == null ? position : position - 1; } @Override public void onBindViewHolder(ViewHolder arg0, final int position) { Log.d("HK", "onBindViewHolder called "+position); if(getItemViewType(position) == TYPE_HEADER) return; final int pos = getRealPosition(arg0); final Product data = products.get(pos); if(arg0 instanceof MasonryView) { ((MasonryView) arg0).textView.setText(products.get(position).getTitle()); ((MasonryView) arg0).imageView.setImageResource(products.get(position).getImg()); } ImageView image = ((MasonryView)arg0).imageView; TextView text = ((MasonryView)arg0).textView; image.setImageResource(products.get(position).getImg()); text.setText(products.get(position).getTitle()); View view = ((MasonryView)arg0).view; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { Log.d("HK", "onCreateViewHolder called "+viewType); if(mHeaderView != null && viewType == TYPE_HEADER) return new MasonryView(mHeaderView); View layout = LayoutInflater.from(parent.getContext()).inflate(R.layout.receycler_item, parent, false); return new MasonryView(layout); } class MasonryView extends RecyclerView.ViewHolder{ ImageView imageView; TextView textView; View view; public MasonryView(View itemView){ super(itemView); view = itemView; imageView= (ImageView) itemView.findViewById(R.id.item_img ); textView= (TextView) itemView.findViewById(R.id.item_title); } }}
在这个适配其中,通过onBindViewHolder来进行数据的绑定,而通过onCreateViewHolder来返回视图。代码中出现的mHeaderView等将在后文进行介绍。
有了这个适配器后,通过上一段的代码,就可以呈现出ListView的显示效果了。当然,如果需要将显示效果更改为gridview,只需要将
recyclerView.setLayoutManager(new LinearLayoutManager(this));更改为 mRecyclerView.setLayoutManager(new GridLayoutManager(this,4))就行。
当然如果要加上分割线,只需要添加
SpacesItemDecoration spaces = new SpacesItemDecoration(16); recyclerView.addItemDecoration(spaces);
SpacesItemDecoration 是自定义的一个类,可以设置分割线的样式等。
public class SpacesItemDecoration extends RecyclerView.ItemDecoration { private int space; public SpacesItemDecoration(int space) { this.space=space; } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { outRect.left=space; outRect.right=space; outRect.bottom=space;// outRect.top=space; if(parent.getChildAdapterPosition(view)==0){// outRect.top=space; } }
如果需要对recyclerview中添加点击事件,则需要自己在适配器中添加接口,添加方式也比较简单。代码如下:
现在适配器中设置一个回调。
private OnItemClickLitener mOnItemClickLitener; public interface OnItemClickLitener { void onItemClick(View view, int position); void onItemLongClick(View view , int position); } public void onBindViewHolder(final ViewHolder viewholder, final int position) { ...... if (mOnItemClickLitener != null) { viewholder.itemView.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { int pos = viewholder.getLayoutPosition(); mOnItemClickLitener.onItemClick(viewholder.itemView, pos); } }); viewholder.itemView.setOnLongClickListener(new OnLongClickListener() { @Override public boolean onLongClick(View v) { int pos = viewholder.getLayoutPosition(); mOnItemClickLitener.onItemLongClick(viewholder.itemView, pos); return false; } }); } } }
接下来在需要点击的地方实现回调
adapter.setOnItemClickLitener(new OnItemClickLitener() { @Override public void onItemClick(View view, int position) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, position + " click", Toast.LENGTH_SHORT).show(); } @Override public void onItemLongClick(View view, int position) { // TODO Auto-generated method stub Toast.makeText(MainActivity.this, position + " long click", Toast.LENGTH_SHORT).show(); //mAdapter.removeData(position); } });
(二)为Recycler添加头部和底部
RecyclerView支持在容器中添加头部和底部来打造优美的视觉效果。由于头部和底部都是作为recyvlerview容易的一个view。为了将其与普通的ItemView进行区分,则需要使用到public int getItemViewType(int position)。先来看看在适配器中代码。
private View mHeaderView; private View mFooterView; public static final int TYPE_HEADER = 0; public static final int TYPE_NORMAL = 1; public static final int TYPE_FOOTER = 2; public void setHeaderView(View headerView) { mHeaderView = headerView; notifyItemInserted(0); Log.d("HK", "setHeaderView called" ); } public void setFooterView(View footerView) { mFooterView = footerView; int footIndex = getItemCount()-1; notifyItemInserted(footIndex); Log.d("HK", "setFooterView called and index = "+footIndex); } public void onBindViewHolder(final ViewHolder viewholder, final int position) { // TODO Auto-generated method stub if(getItemViewType(position) == TYPE_HEADER) return; if(getItemViewType(position) == TYPE_FOOTER) return; final int pos = getRealPosition(viewholder); Log.d("HK", "onBindViewHolder called position pos "+position+" "+pos); } public int getItemViewType(int position) { Log.d("HK", "getItemViewType called "+position); if((mHeaderView == null) && (mFooterView == null)) return TYPE_NORMAL; if(position == 0) return TYPE_HEADER; if(position == getItemCount()-1) return TYPE_FOOTER; return TYPE_NORMAL; }
上面的代码中在适配器中添加了增加头部的函数,增加底部的函数以及对VIEW类型的返回。因为加入了头部和底部,那么普通item的位置就和为添加之前有了一定的差别,因此为了获取位置,我们使用了getRealPosition(viewholder);
public int getRealPosition(RecyclerView.ViewHolder holder) { int position = holder.getLayoutPosition(); Log.d("HK", "getRealPosition called "+position); return mHeaderView == null ? position : position - 1; }
将适配器做完改造后,只需要在使用中进行调用就行。
setHeader(recyclerView); setFooter(recyclerView); private void setFooter(RecyclerView view) { View footerView = LayoutInflater.from(this).inflate(R.layout.footerlayout, view, false); adapter.setFooterView(footerView); } private void setHeader(RecyclerView view) { View header = LayoutInflater.from(this).inflate(R.layout.titlelayout, view, false); adapter.setHeaderView(header); }
但是,按照上述做法我们会发现并不能实现想要的效果。这是应为作为gridview 头部索引为0,如果gridview 分为了多列,那么这个0只会在第一个位置,而不会占用一整行。为了解决这个问题,需要在适配器中添加如下代码。
@Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); RecyclerView.LayoutManager manager = recyclerView.getLayoutManager(); if(manager instanceof GridLayoutManager) { final GridLayoutManager gridManager = ((GridLayoutManager) manager); gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return (getItemViewType(position) == TYPE_HEADER||getItemViewType(position) == TYPE_FOOTER) ? gridManager.getSpanCount() : 1; } }); } }
当然 ,如果我们将样式设置为瀑布流类型就需要添加如下代码:
@Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { super.onViewAttachedToWindow(holder); ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); if(lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams) { StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) lp; if(holder.getLayoutPosition() == 0 ||(holder.getLayoutPosition() == getItemCount()-1)) { p.setFullSpan(true); } } }
以上代码可在GITHUB下载。
GIT:https://github.com/everyhappy/RecyclerViewDemo
- android常用控件RecyclerView(三) RecyclerView的使用
- Android常用控件--RecyclerView的简单使用
- Android RecyclerView 梦幻般的控件 使用解析(三)
- RecyclerView控件的使用
- RecyclerView控件的使用
- [Android]关于RecyclerView控件的使用
- Android 高级编程 RecyclerView 控件的使用
- Android控件之RecyclerView的基本使用
- Android 控件 RecyclerView 的基本使用
- Android RecyclerView控件的使用(一)
- Android RecyclerView 梦幻般的控件 使用解析(一)
- Android RecyclerView 梦幻般的控件 使用解析(二)
- Android RecyclerView使用详解(三)
- [Android]使用RecyclerView替代ListView(三)
- Android RecyclerView使用详解三
- Android -- RecyclerView的使用
- Android RecyclerView的使用
- Android RecyclerView的使用
- android wear-创建Notification
- java之插入排序
- 总结
- 注册表注入
- 软件开发的一般流程
- android常用控件RecyclerView(三) RecyclerView的使用
- 浅析User Agent Stylesheet属性
- java web过滤器在登录时的使用
- 无DLL注入(函数直接注入)
- Hadoop中maper和reducer数目的调节
- DOS磁盘操作系统常用命令总结
- 自定义属性format大全和使用方法
- 十大Intellij IDEA快捷键
- 【并行计算与CUDA开发】基于NVIDIA显卡的硬编解码的一点心得 (完结)