Android5.X (六) : RecycleView
2016-01-21 15:56
381 查看
RecycleView:它是谷歌替代ListView的控件,它拥有ListView的item的回收复用功能,但是RecycleView可以把ViewHolder的实现封装起来,我们只要实现自己的ViewHolder就可以了。
跟RecycleView息息相关的几个类有:
ViewHodler:需要继承RecyleView的ViewHolder
Adapter:适配器:需要继承RecycleView的Adapter
LayoutManager:用来设置用户的展示方式
ItemDecoration:用来设置分隔线的样式
ItemAnimator:关注Item的删除增加动画效果
所以它可以实现ListView,GridView,横向ListView,横向GridView,瀑布流,Item的删除添加动画的设置
第二步:跟ListView一样设置adapter
第三部:自定义它的分割线,因为谷歌并没有提供分割线,所以需要继承ItemDecoration
如果是ListView可以使用这个类:
GridView可以使用这个类:
第四步:设置它的显示模式:
它的manager有以下几种:
设置删除添加动画:Google它提供了默认的删除添加动画
第六步:添加item的点击事件
这个只要在adapter中写一个接口就可以啦
这样就算大功告成啦!
但是如果每个都这样写,那是不是很麻烦?
有空的话,我会抽取出一个基类出来,供大家使用~
跟RecycleView息息相关的几个类有:
ViewHodler:需要继承RecyleView的ViewHolder
Adapter:适配器:需要继承RecycleView的Adapter
LayoutManager:用来设置用户的展示方式
ItemDecoration:用来设置分隔线的样式
ItemAnimator:关注Item的删除增加动画效果
所以它可以实现ListView,GridView,横向ListView,横向GridView,瀑布流,Item的删除添加动画的设置
[code]//第一步:编写Adapter和ViewHolder public class SimpleAdapter extends RecyclerView.Adapter<MyViewHodler> { private LayoutInflater mInflater; private List<String> datas; private Context context; public SimpleAdapter(Context context,List<String> datas) { this.context = context; this.datas = datas; mInflater = LayoutInflater.from(context); } /** * 创建ViewHolder * @param parent * @param viewType * @return */ @Override public MyViewHodler onCreateViewHolder(ViewGroup parent, int viewType) { View v = mInflater.inflate(R.layout.item_text,parent,false); MyViewHodler viewHodler = new MyViewHodler(v); return viewHodler; } /** * 绑定ViewHolder * @param holder * @param position */ @Override public void onBindViewHolder(MyViewHodler holder, int position) { holder.tv.setText(datas.get(position)); } @Override public int getItemCount() { return datas.size(); } } class MyViewHodler extends RecyclerView.ViewHolder { TextView tv; public MyViewHodler(View itemView) { super(itemView); tv = (TextView) itemView.findViewById(R.id.tv_item); } }
第二步:跟ListView一样设置adapter
[code] rv = (RecyclerView) findViewById(R.id.recylerView); rv.setAdapter(new SimpleAdapter(this, datas));
第三部:自定义它的分割线,因为谷歌并没有提供分割线,所以需要继承ItemDecoration
如果是ListView可以使用这个类:
[code]package com.recyleview; 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 DividerItemDecoration 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 DividerItemDecoration(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) { 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); } } }
GridView可以使用这个类:
[code]package com.recyleview; 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.GridLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.LayoutManager; import android.support.v7.widget.RecyclerView.State; import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.View; public class DividerGridItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[] { android.R.attr.listDivider }; private Drawable mDivider; public DividerGridItemDecoration(Context context) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); a.recycle(); } @Override public void onDraw(Canvas c, RecyclerView parent, State state) { drawHorizontal(c, parent); drawVertical(c, parent); } private int getSpanCount(RecyclerView parent) { // 列数 int spanCount = -1; LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { spanCount = ((GridLayoutManager) layoutManager).getSpanCount(); } else if (layoutManager instanceof StaggeredGridLayoutManager) { spanCount = ((StaggeredGridLayoutManager) layoutManager) .getSpanCount(); } return spanCount; } public void drawHorizontal(Canvas c, RecyclerView parent) { 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.getLeft() - params.leftMargin; final int right = child.getRight() + params.rightMargin + mDivider.getIntrinsicWidth(); final int top = child.getBottom() + params.bottomMargin; final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } public void drawVertical(Canvas c, RecyclerView parent) { 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.getTop() - params.topMargin; final int bottom = child.getBottom() + params.bottomMargin; final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicWidth(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } private boolean isLastColum(RecyclerView parent, int pos, int spanCount, int childCount) { LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边 { return true; } } else if (layoutManager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager) .getOrientation(); if (orientation == StaggeredGridLayoutManager.VERTICAL) { if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边 { return true; } } else { childCount = childCount - childCount % spanCount; if (pos >= childCount)// 如果是最后一列,则不需要绘制右边 return true; } } return false; } private boolean isLastRaw(RecyclerView parent, int pos, int spanCount, int childCount) { LayoutManager layoutManager = parent.getLayoutManager(); if (layoutManager instanceof GridLayoutManager) { childCount = childCount - childCount % spanCount; if (pos >= childCount)// 如果是最后一行,则不需要绘制底部 return true; } else if (layoutManager instanceof StaggeredGridLayoutManager) { int orientation = ((StaggeredGridLayoutManager) layoutManager) .getOrientation(); // StaggeredGridLayoutManager 且纵向滚动 if (orientation == StaggeredGridLayoutManager.VERTICAL) { childCount = childCount - childCount % spanCount; // 如果是最后一行,则不需要绘制底部 if (pos >= childCount) return true; } else // StaggeredGridLayoutManager 且横向滚动 { // 如果是最后一行,则不需要绘制底部 if ((pos + 1) % spanCount == 0) { return true; } } } return false; } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { int spanCount = getSpanCount(parent); int childCount = parent.getAdapter().getItemCount(); if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部 { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边 { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight()); } } }
[code] //设置分割线 rv.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));
第四步:设置它的显示模式:
它的manager有以下几种:
[code] //设置垂直的ListView linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL,false); rv.setLayoutManager(linearLayoutManager);
[code] //设置成GridView模式,3列 GridLayoutManager gridLayoutManager = new GridLayoutManager(this,3); rv.setLayoutManager(gridLayoutManager); rv.addItemDecoration(new DividerGridItemDecoration(this)); //横向GridView模式,5行 StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(5,StaggeredGridLayoutManager.HORIZONTAL); rv.setLayoutManager(staggeredGridLayoutManager); //瀑布流模式:3列 StaggeredGridLayoutManager sta = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL); rv.setLayoutManager(sta);
设置删除添加动画:Google它提供了默认的删除添加动画
[code]第五步: // 设置item动画 rv.setItemAnimator(new DefaultItemAnimator());
第六步:添加item的点击事件
这个只要在adapter中写一个接口就可以啦
[code] private onItemClickListener lisener; public interface onItemClickListener{ void onClick(View itemView, int pos); } public void setOnItemClickLisener(onItemClickListener lisener){ this.lisener = lisener; } @Override public void onBindViewHolder(final MyViewHodler holder, int position) { ViewGroup.LayoutParams params = holder.itemView.getLayoutParams(); params.height = heights.get(position); holder.itemView.setLayoutParams(params); holder.tv.setText(datas.get(position)); if(lisener != null){ holder.itemView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int pos = holder.getLayoutPosition(); lisener.onClick(holder.itemView,pos); } }); } }
这样就算大功告成啦!
但是如果每个都这样写,那是不是很麻烦?
有空的话,我会抽取出一个基类出来,供大家使用~
相关文章推荐
- android开发问题汇总
- 31.Android之常用单位px、dip、sp学习
- android之屏幕适配之一理论知识
- Android之Toolbar的使用
- Android开发之Intent.Action
- 走向Android5.0之toolbar,Snackbar
- android 录制短音频
- Android 获取系统联系人并排序
- Android学习历程7-Activity详解
- android代码集锦
- AndroidManifest.xml配置文件详解
- Android Studio 图片资源引用杂谈
- Android小问题:android studio怎么查看数字签名 sha1(地图)
- Cordova / PhoneGap开发入门,基于HTML、CSS和JavaScript的Android移动开发框架
- android技巧(五)一个异步+接口回调的例子
- Android数据存储
- Android working with Google Maps V2
- Android Studio集成crashlytics后无法编译的问题
- Android中使用【microlog4】进行日志存储
- 初识Face++在android上的应用