RecycleView

RecycleViewRecycleViewRecycleView


那么有了ListView、GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。

  • 你想要控制其显示的方式,请通过布局管理器LayoutManager
  • 你想要控制Item间的间隔(可绘制),请通过ItemDecoration
  • 你想要控制Item增删的动画,请通过ItemAnimator
  • 你想要控制点击、长按事件,请自己写(擦,这点尼玛。)
mRecyclerView = findView(R.id.id_recyclerview);

//设置布局管理器

mRecyclerView.setLayoutManager(layout);

//设置adapter

mRecyclerView.setAdapter(adapter)

//设置Item增加、移除动画

mRecyclerView.setItemAnimator(new DefaultItemAnimator());

//添加分割线

mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.HORIZONTAL_LIST));


RecyclerView.LayoutManager吧,这是一个抽象类,好在系统提供了3个实现类:

  1. LinearLayoutManager 现行管理器,支持横向、纵向。
  2. GridLayoutManager 网格布局管理器
  3. StaggeredGridLayoutManager 瀑布就式布局管理器


http://blog.csdn.net/lmj623565791/article/details/45059587; 
推荐【张鸿洋的博客】



demo一粒  注释相当的全面 以供以后参考使用

RecycleAdapter

[java] view plain copy
  1. package com.example.ban.myapplication;  
  2.   
  3. import android.content.Context;  
  4. import android.support.v7.widget.RecyclerView;  
  5. import android.view.LayoutInflater;  
  6. import android.view.View;  
  7. import android.view.ViewGroup;  
  8. import android.widget.TextView;  
  9.   
  10. import java.util.List;  
  11.   
  12. /** 
  13.  * Created by ban on 2016/11/24. 
  14.  * <p> 
  15.  * 创建适配器类继承RecycleView的Adapter,步骤为: 
  16.  * <p> 
  17.  * 1、继承RecyclerView.Adapter,并且在Adapter里面声明ViewHolder类继承RecyclerView 
  18.  * .ViewHolder,最后把自己的ViewHolder类丢进自己的Adapter类的泛型中去。 
  19.  * 2、在自定义ViewHolder类的构造方法中可以通过ID找到布局的控件,控件需要声明为自定义ViewHolder类的成员变量。 
  20.  * 3、实现RecyclerView.Adapter的所有未实现的函数,onCreateViewHolder主要负责加载布局 
  21.  * (加载的时候注意要把父布局写到参数里去),创建自定义ViewHolder 
  22.  * 类的对象;onBindViewHolder主要负责把数据设置到Item的控件中;getItemCount主要负责得到数据的数目。 
  23.  * 4、最好把数据声明为成员变量,在构造函数里面传进来。 
  24.  * 5、由于RecycleView原生不支持点击事件,需要自己添加接口进行回调。 
  25.  */  
  26.   
  27. public class RecycleAdapter extends RecyclerView.Adapter<RecycleAdapter.MyViewHolder> {  
  28.   
  29.     List<String> mDatas = null;  
  30.     Context mContext = null;  
  31.   
  32.     //构造方法,这里还是和使用BaseAdapter的行为习惯一直  
  33.     //通过构造函数把要显示的数据读取进来  
  34.     public RecycleAdapter(List<String> mDatas, Context mContext) {  
  35.         this.mDatas = mDatas;  
  36.         this.mContext = mContext;  
  37.     }  
  38.   
  39.   
  40.     /** 
  41.      * 创建泛型中的ViewHolder的方法 
  42.      * 
  43.      * @param parent   父布局 
  44.      * @param viewType Item类型,根据类型可以指定不同的显示布局,重写getItemViewType()方法 
  45.      * @return 泛型中的ViewHolder对象 
  46.      * <p> 
  47.      * 补充:关于viewType 
  48.      * 可以通过Adapter的getViewType(int position)方法实现多种不同的条目。 
  49.      * 具体做法是根据position的不同例如奇数偶数,或者特定值,然后根据viewType参数的不同去inflate不同的item布局即可 
  50.      */  
  51.     //负责加载布局   //相当于ListView中的getView()方法  
  52.     @Override  
  53.     public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {  
  54.         //加载布局的时候需要注意要把parent传进去  
  55.         return new MyViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout  
  56.                 .item_view, parent, false));  
  57.     }  
  58.   
  59.     /** 
  60.      * 创建完成ViewHolder之后需要进行绑定,相当于为每个Item进行赋值,绘制Item的 
  61.      * 
  62.      * @param holder   onCreateViewHolder()方法创建出来的泛型中的ViewHolder 
  63.      * @param position 位置 
  64.      */  
  65.     // 把数据设置到item的控件中  //在这里需要设置显示的数据  
  66.     @Override  
  67.     public void onBindViewHolder(MyViewHolder holder, int position) {  
  68.         holder.tv_num.setText(mDatas.get(position));  
  69.     }  
  70.   
  71.     /** 
  72.      * 获取条目数量 
  73.      * 
  74.      * @return 数量 
  75.      */  
  76.     //主要负责得到数据的数目。  
  77.     @Override  
  78.     public int getItemCount() {  
  79.         return mDatas.size();  
  80.     }  
  81.   
  82.     //自定义ViewHolder必须继承RecyclerView.ViewHolder,在构造函数中进行ID绑定控件,条目监听等  
  83.     public class MyViewHolder extends RecyclerView.ViewHolder {  
  84.         TextView tv_num;  
  85.   
  86.         public MyViewHolder(final View itemView) {  
  87.             super(itemView);  
  88.             tv_num = (TextView) itemView.findViewById(R.id.tv);  
  89.             tv_num.setOnClickListener(new View.OnClickListener() {  
  90.                 @Override  
  91.                 public void onClick(View view) {  
  92.                     if (onItemClickListener != null) {  
  93.                         onItemClickListener.onItemClick(itemView, getLayoutPosition(), mDatas.get  
  94.                                 (getLayoutPosition()));  
  95.                     }  
  96.                 }  
  97.             });  
  98.         }  
  99.     }  
  100.   
  101.     //自定义监听  
  102.     private OnItemClickListener onItemClickListener;  
  103.   
  104.     //定义一个接口  
  105.     public interface OnItemClickListener {  
  106.         void onItemClick(View v, int position, String data);  
  107.     }  
  108.   
  109.     public void setOnItemClickListener(OnItemClickListener listener) {  
  110.         this.onItemClickListener = listener;  
  111.     }  
  112.   
  113.     public void addData(int position, String data) {  
  114.         mDatas.add(position, data);  
  115.         notifyItemInserted(position);  
  116.   
  117.     }  
  118.   
  119.     public void removeData(int position) {  
  120.         mDatas.remove(position);  
  121.         notifyItemRemoved(position);  
  122.     }  
  123.   
  124. }  

RecycleDemoActivity

[java] view plain copy
  1. package com.example.ban.myapplication;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.support.v7.widget.DefaultItemAnimator;  
  6. import android.support.v7.widget.GridLayoutManager;  
  7. import android.support.v7.widget.LinearLayoutManager;  
  8. import android.support.v7.widget.RecyclerView;  
  9. import android.support.v7.widget.StaggeredGridLayoutManager;  
  10. import android.view.Menu;  
  11. import android.view.MenuItem;  
  12. import android.view.View;  
  13. import android.widget.Toast;  
  14.   
  15. import java.util.ArrayList;  
  16. import java.util.List;  
  17.   
  18. /** 
  19.  * Created by ban on 2016/11/24. 
  20.  * Activity中需要处理的核心的步骤 
  21.  * <p> 
  22.  * 1、通过ID找到RecyclerView。 
  23.  * 2、RecyclerView设置Adapter。 
  24.  * 3、RecyclerView设置布局管理器,常用的布局管理器有LinearLayoutManager:线性布局, 
  25.  * 4、LayoutManager的实现类,类型包括Vertical和HorizontalGridLayoutManager;格子布局,继承自LinearLayoutManager 
  26.  * ,实现效果类似GridView;StaggeredGridLayoutManager交错的格子布局,同样也是LayoutManager的实现类,类型包括Vertical 
  27.  * 和Horizontal,与GridLayoutManager很相似,不过是交错的格子,也就是宽高不等的格子视图,类似瀑布流的效果。 
  28.  * 5、RecyclerView设置数据插入、删除的时候的动画效果,这里使用默认的。下面的网址是GitHub上面的开源动画效果: 
  29.  * https://github.com/gabrielemariotti/RecyclerViewItemAnimators 
  30.  * 6、RecyclerView设置Item之间的装饰器,这里也是使用GitHub提供的装饰器,代码会在附件中给出。 
  31.  */  
  32.   
  33. public class RecycleDemoActivity extends Activity {  
  34.   
  35.     List<String> datas = null;  
  36.     private RecyclerView recyclerView;  
  37.     private RecycleAdapter myAdapter;  
  38.   
  39.     @Override  
  40.     protected void onCreate(Bundle savedInstanceState) {  
  41.         super.onCreate(savedInstanceState);  
  42.         setContentView(R.layout.recycle);  
  43.         initData();  
  44.         recyclerView = (RecyclerView) findViewById(R.id.recycleview);  
  45.   
  46.         //设置RecycleView的适配器  
  47.         myAdapter = new RecycleAdapter(datas, this);  
  48.         recyclerView.setAdapter(myAdapter);  
  49.         //设置布局管理器,以渲染出不同的效果  
  50.         recyclerView.setLayoutManager(new LinearLayoutManager(this));  
  51.         //设置插入、删除数据的动画效果(这里使用默认的动画)  
  52.         recyclerView.setItemAnimator(new DefaultItemAnimator());  
  53.         //设置每个Item之间的装饰(这里设置为分隔线)  
  54.         recyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration  
  55.                 .VERTICAL_LIST));  
  56.   
  57.         myAdapter.setOnItemClickListener(new RecycleAdapter.OnItemClickListener() {  
  58.             @Override  
  59.             public void onItemClick(View v, int position, String data) {  
  60.                 Toast.makeText(RecycleDemoActivity.this, data, Toast.LENGTH_SHORT).show();  
  61.             }  
  62.         });  
  63.   
  64.     }  
  65.   
  66.     private void initData() {  
  67.         datas = new ArrayList<>();  
  68.         for (int i = 0; i < 300; i++) {  
  69.             datas.add(i + "===");  
  70.         }  
  71.     }  
  72.     @Override  
  73.     public boolean onCreateOptionsMenu(Menu menu) {  
  74.         getMenuInflater().inflate(R.menu.menu_main, menu);  
  75.         return super.onCreateOptionsMenu(menu);  
  76.     }  
  77.   
  78.     @Override  
  79.     public boolean onOptionsItemSelected(MenuItem item) {  
  80.         switch (item.getItemId()) {  
  81.             case R.id.action_add:  
  82.                 myAdapter.addData(0"new data");  
  83.                 recyclerView.scrollToPosition(0);  
  84.                 break;  
  85.             case R.id.action_delete:  
  86.                 myAdapter.removeData(0);  
  87.                 break;  
  88.             case R.id.action_gridview:  
  89.                 recyclerView.setLayoutManager(new GridLayoutManager(this4));  
  90.                 break;  
  91.             case R.id.action_listview:  
  92.                 recyclerView.setLayoutManager(new LinearLayoutManager(this));  
  93.                 break;  
  94.             case R.id.action_staggeredgridview:  
  95.                 recyclerView.setLayoutManager(new StaggeredGridLayoutManager(6,  
  96.                         StaggeredGridLayoutManager.VERTICAL));  
  97.                 break;  
  98.   
  99.         }  
  100.         return true;  
  101.     }  
  102. }  

DividerGridItemDecoration

[java] view plain copy
  1. package com.example.ban.myapplication;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Rect;  
  7. import android.graphics.drawable.Drawable;  
  8. import android.support.v7.widget.GridLayoutManager;  
  9. import android.support.v7.widget.RecyclerView;  
  10. import android.support.v7.widget.StaggeredGridLayoutManager;  
  11. import android.view.View;  
  12.   
  13. /** 
  14.  * Created by ban on 2016/11/24. 
  15.  */  
  16.   
  17. public class DividerGridItemDecoration extends RecyclerView.ItemDecoration  
  18. {  
  19.   
  20.     private static final int[] ATTRS = new int[] { android.R.attr.listDivider };  
  21.     private Drawable mDivider;  
  22.   
  23.     public DividerGridItemDecoration(Context context)  
  24.     {  
  25.         final TypedArray a = context.obtainStyledAttributes(ATTRS);  
  26.         mDivider = a.getDrawable(0);  
  27.         a.recycle();  
  28.     }  
  29.   
  30.     @Override  
  31.     public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state)  
  32.     {  
  33.   
  34.         drawHorizontal(c, parent);  
  35.         drawVertical(c, parent);  
  36.   
  37.     }  
  38.   
  39.     private int getSpanCount(RecyclerView parent)  
  40.     {  
  41.         // 列数  
  42.         int spanCount = -1;  
  43.         RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();  
  44.         if (layoutManager instanceof GridLayoutManager)  
  45.         {  
  46.   
  47.             spanCount = ((GridLayoutManager) layoutManager).getSpanCount();  
  48.         } else if (layoutManager instanceof StaggeredGridLayoutManager)  
  49.         {  
  50.             spanCount = ((StaggeredGridLayoutManager) layoutManager)  
  51.                     .getSpanCount();  
  52.         }  
  53.         return spanCount;  
  54.     }  
  55.   
  56.     public void drawHorizontal(Canvas c, RecyclerView parent)  
  57.     {  
  58.         int childCount = parent.getChildCount();  
  59.         for (int i = 0; i < childCount; i++)  
  60.         {  
  61.             final View child = parent.getChildAt(i);  
  62.             final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child  
  63.                     .getLayoutParams();  
  64.             final int left = child.getLeft() - params.leftMargin;  
  65.             final int right = child.getRight() + params.rightMargin  
  66.                     + mDivider.getIntrinsicWidth();  
  67.             final int top = child.getBottom() + params.bottomMargin;  
  68.             final int bottom = top + mDivider.getIntrinsicHeight();  
  69.             mDivider.setBounds(left, top, right, bottom);  
  70.             mDivider.draw(c);  
  71.         }  
  72.     }  
  73.   
  74.     public void drawVertical(Canvas c, RecyclerView parent)  
  75.     {  
  76.         final int childCount = parent.getChildCount();  
  77.         for (int i = 0; i < childCount; i++)  
  78.         {  
  79.             final View child = parent.getChildAt(i);  
  80.   
  81.             final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child  
  82.                     .getLayoutParams();  
  83.             final int top = child.getTop() - params.topMargin;  
  84.             final int bottom = child.getBottom() + params.bottomMargin;  
  85.             final int left = child.getRight() + params.rightMargin;  
  86.             final int right = left + mDivider.getIntrinsicWidth();  
  87.   
  88.             mDivider.setBounds(left, top, right, bottom);  
  89.             mDivider.draw(c);  
  90.         }  
  91.     }  
  92.   
  93.     private boolean isLastColum(RecyclerView parent, int pos, int spanCount,  
  94.                                 int childCount)  
  95.     {  
  96.         RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();  
  97.         if (layoutManager instanceof GridLayoutManager)  
  98.         {  
  99.             if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边  
  100.             {  
  101.                 return true;  
  102.             }  
  103.         } else if (layoutManager instanceof StaggeredGridLayoutManager)  
  104.         {  
  105.             int orientation = ((StaggeredGridLayoutManager) layoutManager)  
  106.                     .getOrientation();  
  107.             if (orientation == StaggeredGridLayoutManager.VERTICAL)  
  108.             {  
  109.                 if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边  
  110.                 {  
  111.                     return true;  
  112.                 }  
  113.             } else  
  114.             {  
  115.                 childCount = childCount - childCount % spanCount;  
  116.                 if (pos >= childCount)// 如果是最后一列,则不需要绘制右边  
  117.                     return true;  
  118.             }  
  119.         }  
  120.         return false;  
  121.     }  
  122.   
  123.     private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,  
  124.                               int childCount)  
  125.     {  
  126.         RecyclerView.LayoutManager layoutManager = parent.getLayoutManager();  
  127.         if (layoutManager instanceof GridLayoutManager)  
  128.         {  
  129.             childCount = childCount - childCount % spanCount;  
  130.             if (pos >= childCount)// 如果是最后一行,则不需要绘制底部  
  131.                 return true;  
  132.         } else if (layoutManager instanceof StaggeredGridLayoutManager)  
  133.         {  
  134.             int orientation = ((StaggeredGridLayoutManager) layoutManager)  
  135.                     .getOrientation();  
  136.             // StaggeredGridLayoutManager 且纵向滚动  
  137.             if (orientation == StaggeredGridLayoutManager.VERTICAL)  
  138.             {  
  139.                 childCount = childCount - childCount % spanCount;  
  140.                 // 如果是最后一行,则不需要绘制底部  
  141.                 if (pos >= childCount)  
  142.                     return true;  
  143.             } else  
  144.             // StaggeredGridLayoutManager 且横向滚动  
  145.             {  
  146.                 // 如果是最后一行,则不需要绘制底部  
  147.                 if ((pos + 1) % spanCount == 0)  
  148.                 {  
  149.                     return true;  
  150.                 }  
  151.             }  
  152.         }  
  153.         return false;  
  154.     }  
  155.   
  156.     @Override  
  157.     public void getItemOffsets(Rect outRect, int itemPosition,  
  158.                                RecyclerView parent)  
  159.     {  
  160.         int spanCount = getSpanCount(parent);  
  161.         int childCount = parent.getAdapter().getItemCount();  
  162.         if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部  
  163.         {  
  164.             outRect.set(00, mDivider.getIntrinsicWidth(), 0);  
  165.         } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边  
  166.         {  
  167.             outRect.set(000, mDivider.getIntrinsicHeight());  
  168.         } else  
  169.         {  
  170.             outRect.set(00, mDivider.getIntrinsicWidth(),  
  171.                     mDivider.getIntrinsicHeight());  
  172.         }  
  173.     }  
  174. }  

DividerItemDecoration

[java] view plain copy
  1. package com.example.ban.myapplication;  
  2.   
  3. import android.content.Context;  
  4. import android.content.res.TypedArray;  
  5. import android.graphics.Canvas;  
  6. import android.graphics.Rect;  
  7. import android.graphics.drawable.Drawable;  
  8. import android.support.v7.widget.LinearLayoutManager;  
  9. import android.support.v7.widget.RecyclerView;  
  10. import android.view.View;  
  11.   
  12. /** 
  13.  * Created by ban on 2016/11/24. 
  14.  */  
  15.   
  16. public class DividerItemDecoration extends RecyclerView.ItemDecoration  
  17. {  
  18.   
  19.     private static final int[] ATTRS = new int[] { android.R.attr.listDivider };  
  20.   
  21.     public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;  
  22.   
  23.     public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;  
  24.   
  25.   
  26.   
  27.     private Drawable mDivider;  
  28.   
  29.     private int mOrientation;  
  30.   
  31.     public DividerItemDecoration(Context context, int orientation)  
  32.     {  
  33.         final TypedArray a = context.obtainStyledAttributes(ATTRS);  
  34.         mDivider = a.getDrawable(0);  
  35.         a.recycle();  
  36.         setOrientation(orientation);  
  37.     }  
  38.   
  39.     public void setOrientation(int orientation)  
  40.     {  
  41.         if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST)  
  42.         {  
  43.             throw new IllegalArgumentException("invalid orientation");  
  44.         }  
  45.         mOrientation = orientation;  
  46.     }  
  47.   
  48.     @Override  
  49.     public void onDraw(Canvas c, RecyclerView parent)  
  50.     {  
  51.         if (mOrientation == VERTICAL_LIST) {  
  52.             drawVertical(c, parent);  
  53.         } else {  
  54.             drawHorizontal(c, parent);  
  55.         }  
  56.     }  
  57.   
  58.     public void drawVertical(Canvas c, RecyclerView parent)  
  59.     {  
  60.         final int left = parent.getPaddingLeft();  
  61.         final int right = parent.getWidth() - parent.getPaddingRight();  
  62.   
  63.         final int childCount = parent.getChildCount();  
  64.   
  65.         for (int i = 0; i < childCount; i++)  
  66.         {  
  67.             final View child = parent.getChildAt(i);  
  68.             android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(  
  69.                     parent.getContext());  
  70.             final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child  
  71.                     .getLayoutParams();  
  72.             final int top = child.getBottom() + params.bottomMargin;  
  73.             final int bottom = top + mDivider.getIntrinsicHeight();  
  74.             mDivider.setBounds(left, top, right, bottom);  
  75.             mDivider.draw(c);  
  76.         }  
  77.     }  
  78.   
  79.     public void drawHorizontal(Canvas c, RecyclerView parent)  
  80.     {  
  81.         final int top = parent.getPaddingTop();  
  82.         final int bottom = parent.getHeight() - parent.getPaddingBottom();  
  83.   
  84.         final int childCount = parent.getChildCount();  
  85.         for (int i = 0; i < childCount; i++)  
  86.         {  
  87.             final View child = parent.getChildAt(i);  
  88.             final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child  
  89.                     .getLayoutParams();  
  90.             final int left = child.getRight() + params.rightMargin;  
  91.             final int right = left + mDivider.getIntrinsicHeight();  
  92.             mDivider.setBounds(left, top, right, bottom);  
  93.             mDivider.draw(c);  
  94.         }  
  95.     }  
  96.   
  97.     @Override  
  98.     public void getItemOffsets(Rect outRect, int itemPosition,  
  99.                                RecyclerView parent)  
  100.     {  
  101.         if (mOrientation == VERTICAL_LIST)  
  102.         {  
  103.             outRect.set(000, mDivider.getIntrinsicHeight());  
  104.         } else  
  105.         {  
  106.             outRect.set(00, mDivider.getIntrinsicWidth(), 0);  
  107.         }  
  108.     }  
  109. }  

源码地址:http://download.csdn.net/detail/u010566681/9692767

https://blog.csdn.net/u010566681/article/details/52064791