RecyclerView

控件简单介绍

  • ListView的升级版
  • LinearLayoutManager
  • GridLayoutManager
  • StaggeredGridLayoutManager
  • 定制Item动画,指定Item之间的分隔线

RecyclerView相关的重要类

  • Adapter
  • ViewHolder
  • LayoutManager
  • ItemDecoration
  • ItemAnimator

加入RecyclerView控件依赖包

Android Studio开发工具,在本项目的build.gradle文件里加入

  1. compile 'com.android.support:recyclerview-v7:23.1.1'

假设是eclipse的话,下载jar包。放到lib下。一般都会自己主动的build path,检查下就可以。

怎样下载jar ?

在SDK Manager中下载Support Library

sdk\extras\android\support\v7\recyclerview\libs

为Recycler准备数据

  1. package demo.turing.com.materialdesignwidget.recyclerView;
  2. import java.util.ArrayList;
  3. import demo.turing.com.materialdesignwidget.recyclerView.model.SampleModel;
  4. /**
  5. * MyApp
  6. *
  7. * @author Mr.Yang on 2016-03-30 20:21.
  8. * @version 1.0
  9. * @desc
  10. */
  11. public class SimulatorData {
  12. public static ArrayList<SampleModel> getSampleModelData(int size) {
  13. ArrayList<SampleModel> sampleData = new ArrayList<SampleModel>(size);
  14. for (int i = 0; i < size; i++) {
  15. sampleData.add(new SampleModel("新的列表项< " + i + " >"));
  16. }
  17. return sampleData;
  18. }
  19. }
  1. package demo.turing.com.materialdesignwidget.recyclerView.model;
  2. /**
  3. * MyApp
  4. *
  5. * @author Mr.Yang on 2016-03-30 20:23.
  6. * @version 1.0
  7. * 相应Item中药显示的数据项
  8. */
  9. public class SampleModel {
  10. private String text;
  11. public SampleModel(String text) {
  12. this.text = text;
  13. }
  14. public String getText() {
  15. return text;
  16. }
  17. public void setText(String text) {
  18. this.text = text;
  19. }
  20. }

绘制列表项之间的分隔线

  1. package demo.turing.com.materialdesignwidget.recyclerView;
  2. import android.content.Context;
  3. import android.content.res.TypedArray;
  4. import android.graphics.Canvas;
  5. import android.graphics.Rect;
  6. import android.graphics.drawable.Drawable;
  7. import android.support.v7.widget.LinearLayoutManager;
  8. import android.support.v7.widget.RecyclerView;
  9. import android.view.View;
  10. /**
  11. * MyApp
  12. *
  13. * @author Mr.Yang on 2016-03-30 20:37.
  14. * @version 1.0
  15. * 分隔条
  16. *
  17. *
  18. * DividerItemDecoration https://gist.github.com/alexfu/0f464fc3742f134ccd1e
  19. */
  20. public class DividerItemDecoration extends RecyclerView.ItemDecoration {
  21. // 默认分隔条Drawable资源的ID,使用系统自带的
  22. private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
  23. public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
  24. public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
  25. private Drawable mDivider;
  26. private int mOrientation;
  27. public DividerItemDecoration(Context context, int orientation) {
  28. // 使用TypedArray装载定义的ATTRS
  29. final TypedArray a = context.obtainStyledAttributes(ATTRS);
  30. // 获取系统提供的分隔条Drawable对象
  31. mDivider = a.getDrawable(0);
  32. // 回收TypedArray所占用的空间
  33. a.recycle();
  34. setOrientation(orientation);
  35. }
  36. /**
  37. * 设置item的显示 水平 or 垂直
  38. *
  39. * @param orientation
  40. */
  41. public void setOrientation(int orientation) {
  42. if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
  43. throw new IllegalArgumentException("invalid orientation");
  44. }
  45. mOrientation = orientation;
  46. }
  47. @Override
  48. public void onDraw(Canvas c, RecyclerView parent) {
  49. if (mOrientation == VERTICAL_LIST) {
  50. drawVertical(c, parent);
  51. } else {
  52. drawHorizontal(c, parent);
  53. }
  54. }
  55. public void drawVertical(Canvas c, RecyclerView parent) {
  56. final int left = parent.getPaddingLeft();
  57. final int right = parent.getWidth() - parent.getPaddingRight();
  58. final int childCount = parent.getChildCount();
  59. for (int i = 0; i < childCount; i++) {
  60. final View child = parent.getChildAt(i);
  61. RecyclerView v = new android.support.v7.widget.RecyclerView(
  62. parent.getContext());
  63. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
  64. .getLayoutParams();
  65. final int top = child.getBottom() + params.bottomMargin;
  66. final int bottom = top + mDivider.getIntrinsicHeight();
  67. mDivider.setBounds(left, top, right, bottom);
  68. mDivider.draw(c);
  69. }
  70. }
  71. public void drawHorizontal(Canvas c, RecyclerView parent) {
  72. final int top = parent.getPaddingTop();
  73. final int bottom = parent.getHeight() - parent.getPaddingBottom();
  74. final int childCount = parent.getChildCount();
  75. for (int i = 0; i < childCount; i++) {
  76. final View child = parent.getChildAt(i);
  77. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
  78. .getLayoutParams();
  79. final int left = child.getRight() + params.rightMargin;
  80. final int right = left + mDivider.getIntrinsicHeight();
  81. mDivider.setBounds(left, top, right, bottom);
  82. mDivider.draw(c);
  83. }
  84. }
  85. @Override
  86. public void getItemOffsets(Rect outRect, int itemPosition,
  87. RecyclerView parent) {
  88. if (mOrientation == VERTICAL_LIST) {
  89. outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
  90. } else {
  91. outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
  92. }
  93. }
  94. }

实现Adapter

  1. package demo.turing.com.materialdesignwidget.recyclerView.adapter;
  2. import android.support.v7.widget.RecyclerView;
  3. import android.view.LayoutInflater;
  4. import android.view.View;
  5. import android.view.ViewGroup;
  6. import android.widget.TextView;
  7. import java.util.ArrayList;
  8. import java.util.Random;
  9. import demo.turing.com.materialdesignwidget.R;
  10. import demo.turing.com.materialdesignwidget.recyclerView.SimulatorData;
  11. import demo.turing.com.materialdesignwidget.recyclerView.model.SampleModel;
  12. /**
  13. * MyApp
  14. *
  15. * @author Mr.Yang on 2016-03-30 21:03.
  16. * @version 1.0
  17. * @desc
  18. */
  19. public class SampleRecyclerAdapter extends RecyclerView.Adapter<SampleRecyclerAdapter.ViewHolder> {
  20. // 模拟数据
  21. private ArrayList<SampleModel> sampleData = SimulatorData.getSampleModelData(20);
  22. /**
  23. * 用于创建控件
  24. *
  25. * @param parent
  26. * @param viewType
  27. * @return
  28. */
  29. @Override
  30. public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  31. // 获得列表项控件(LinearLayer对象)
  32. // list_basic_item.xml布局文件里仅仅包括一个<LinearLayer>标签,
  33. // 在该标签中包括了一个<TextView>标签, item是LinearLayout对象
  34. View item = LayoutInflater.from(parent.getContext()).inflate(
  35. R.layout.list_basic_item, parent, false);
  36. ViewHolder viewHolder = new ViewHolder(item);
  37. return viewHolder;
  38. }
  39. /**
  40. * 为控件设置数据
  41. *
  42. * @param holder
  43. * @param position
  44. */
  45. @Override
  46. public void onBindViewHolder(ViewHolder holder, int position) {
  47. // 获取当前item中显示的数据
  48. final SampleModel rowData = sampleData.get(position);
  49. // 设置要显示的数据
  50. holder.textViewSample.setText(rowData.getText());
  51. // 设置tag
  52. holder.itemView.setTag(rowData);
  53. }
  54. @Override
  55. public int getItemCount() {
  56. return sampleData.size();
  57. }
  58. /**
  59. * 删除指定的Item
  60. *
  61. * @param position
  62. */
  63. public void removeData(int position) {
  64. sampleData.remove(position);
  65. // 通知RecyclerView控件某个Item已经被删除
  66. notifyItemRemoved(position);
  67. }
  68. /**
  69. * 在指定位置加入一个新的Item
  70. *
  71. * @param positionToAdd
  72. */
  73. public void addItem(int positionToAdd) {
  74. sampleData.add(positionToAdd, new SampleModel("新的列表项" + new Random().nextInt(10000)));
  75. // 通知RecyclerView控件插入了某个Item
  76. notifyItemInserted(positionToAdd);
  77. }
  78. /**
  79. * 相应Item中的控件
  80. */
  81. public static class ViewHolder extends RecyclerView.ViewHolder {
  82. private final TextView textViewSample;
  83. public ViewHolder(View itemView) {
  84. super(itemView);
  85. textViewSample = (TextView) itemView
  86. .findViewById(R.id.textViewSample);
  87. }
  88. }
  89. }

完毕使用RecyclerView控件的最后工作

  1. package demo.turing.com.materialdesignwidget.recyclerView;
  2. import android.os.Bundle;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.support.v7.widget.LinearLayoutManager;
  5. import android.support.v7.widget.RecyclerView;
  6. import demo.turing.com.materialdesignwidget.R;
  7. import demo.turing.com.materialdesignwidget.recyclerView.adapter.SampleRecyclerAdapter;
  8. public class RecyclerViewAct extends AppCompatActivity {
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_recycler_view);
  13. // 获取RecyclerView对象
  14. RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
  15. // 创建线性布局管理器(默认是垂直方向)
  16. LinearLayoutManager layoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
  17. // 为RecyclerView指定布局管理对象
  18. recyclerView.setLayoutManager(layoutManager);
  19. // 创建列表项分隔线对象
  20. RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST);
  21. // 为RecyclerView控件指定分隔线对象
  22. recyclerView.addItemDecoration(itemDecoration);
  23. SampleRecyclerAdapter sampleRecyclerAdapter = new SampleRecyclerAdapter();
  24. recyclerView.setAdapter(sampleRecyclerAdapter);
  25. }
  26. }

效果图

定制个性化分隔条

drawable\divider_custom.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <shape xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:shape="rectangle">
  4. <size android:height="4dp"></size>
  5. <!--渐变色-->
  6. <gradient
  7. android:centerColor="#ff0000ff"
  8. android:endColor="#ffff0000"
  9. android:startColor="#ffff0000"
  10. android:type="linear"></gradient>
  11. </shape>

主题中设置

  1. <item name="android:listDivider">@drawable/divider_custom</item>

瀑布流

StaggeredGridLayuoutAct.java

  1. package demo.turing.com.materialdesignwidget.recyclerView;
  2. import android.os.Bundle;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.support.v7.widget.RecyclerView;
  5. import android.support.v7.widget.StaggeredGridLayoutManager;
  6. import java.util.List;
  7. import demo.turing.com.materialdesignwidget.R;
  8. import demo.turing.com.materialdesignwidget.recyclerView.adapter.StaggeredGridLayoutAdapter;
  9. import demo.turing.com.materialdesignwidget.recyclerView.model.SampleModel;
  10. /**
  11. * 不採用分隔线, 在Item的布局中 採用layout_margin的方式
  12. *
  13. * 主要是动态设置View的高度 adapter类中的 onBindViewHolder
  14. */
  15. public class StaggeredGridLayuoutAct extends AppCompatActivity {
  16. private RecyclerView recyclerView ;
  17. // 模拟数据
  18. private List<SampleModel> sampleData = SimulatorData.getSampleModelData(20);
  19. @Override
  20. protected void onCreate(Bundle savedInstanceState) {
  21. super.onCreate(savedInstanceState);
  22. setContentView(R.layout.activity_staggered_grid_layuout);
  23. // 查找组件
  24. recyclerView = (RecyclerView) findViewById(R.id.id_rv_staggered);
  25. // 创建布局管理器 -3列,垂直
  26. StaggeredGridLayoutManager manager = new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL);
  27. // 设置布局
  28. recyclerView.setLayoutManager(manager);
  29. // Adapter
  30. StaggeredGridLayoutAdapter adapter = new StaggeredGridLayoutAdapter(this,sampleData);
  31. recyclerView.setAdapter(adapter);
  32. }
  33. }

activity_staggered_grid_layuout.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:tools="http://schemas.android.com/tools"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:paddingBottom="@dimen/activity_vertical_margin"
  7. android:paddingLeft="@dimen/activity_horizontal_margin"
  8. android:paddingRight="@dimen/activity_horizontal_margin"
  9. android:paddingTop="@dimen/activity_vertical_margin"
  10. tools:context="demo.turing.com.materialdesignwidget.recyclerView.StaggeredGridLayuoutAct">
  11. <android.support.v7.widget.RecyclerView
  12. android:id="@+id/id_rv_staggered"
  13. android:layout_width="match_parent"
  14. android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>
  15. </RelativeLayout>

StaggeredGridLayoutAdapter.java

  1. package demo.turing.com.materialdesignwidget.recyclerView.adapter;
  2. import android.content.Context;
  3. import android.support.v7.widget.RecyclerView;
  4. import android.view.LayoutInflater;
  5. import android.view.View;
  6. import android.view.ViewGroup;
  7. import android.widget.TextView;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. import demo.turing.com.materialdesignwidget.R;
  11. import demo.turing.com.materialdesignwidget.recyclerView.model.SampleModel;
  12. /**
  13. * MyApp
  14. *
  15. * @author Mr.Yang on 2016-03-31 20:19.
  16. * @version 1.0
  17. * @desc
  18. */
  19. public class StaggeredGridLayoutAdapter extends RecyclerView.Adapter<StaggeredGridLayoutAdapter.ViewHolder> {
  20. private Context context;
  21. private List<SampleModel> datas;
  22. private LayoutInflater inflater;
  23. // 随机高度的结合
  24. private List<Integer> mHeights;
  25. /**
  26. * 构造函数
  27. *
  28. * @param context
  29. * @param datas
  30. */
  31. public StaggeredGridLayoutAdapter(Context context, List<SampleModel> datas) {
  32. this.context = context;
  33. this.datas = datas;
  34. this.inflater = LayoutInflater.from(context);
  35. // 初始化随机高度的集合
  36. mHeights = new ArrayList<>();
  37. for (int i = 0; i < datas.size(); i++) {
  38. mHeights.add((int)(100 + Math.random() * 300));
  39. }
  40. }
  41. @Override
  42. public StaggeredGridLayoutAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  43. // 动态载入Item的布局文件
  44. View view = inflater.inflate(R.layout.list_basic_item, parent, false);
  45. // 实例化ViewHolder
  46. ViewHolder viewHolder = new ViewHolder(view);
  47. return viewHolder;
  48. }
  49. @Override
  50. public void onBindViewHolder(StaggeredGridLayoutAdapter.ViewHolder holder, int position) {
  51. // 获取当前Item中的显示的数据
  52. SampleModel sampleModel = datas.get(position);
  53. //设置控件的随机高度
  54. ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
  55. lp.height = mHeights.get(position);
  56. holder.itemView.setLayoutParams(lp);
  57. // 设置组件的值
  58. holder.textView.setText(sampleModel.getText());
  59. // 设置tag
  60. holder.itemView.setTag(sampleModel);
  61. }
  62. @Override
  63. public int getItemCount() {
  64. return datas.size();
  65. }
  66. /**
  67. * ViewHoder
  68. */
  69. class ViewHolder extends RecyclerView.ViewHolder {
  70. TextView textView;
  71. public ViewHolder(View itemView) {
  72. super(itemView);
  73. textView = (TextView) itemView
  74. .findViewById(R.id.textViewSample);
  75. }
  76. }
  77. }

list_basic_item.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:layout_margin="3dp"
  6. android:background="#6495ED"
  7. android:gravity="center"
  8. android:orientation="horizontal">
  9. <TextView
  10. android:id="@+id/textViewSample"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:textSize="20sp"
  14. android:text="演示"/>
  15. </RelativeLayout>

效果图

动画效果

  1. // 默认动画效果
  2. recyclerView.setItemAnimator(new DefaultItemAnimator());

notifyItemRemoved(position)

  1. /**
  2. * 删除指定的Item
  3. *
  4. * @param position
  5. */
  6. public void removeData(int position) {
  7. sampleData.remove(position);
  8. // 通知RecyclerView控件某个Item已经被删除
  9. notifyItemRemoved(position);
  10. }

notifyItemInserted(positionToAdd)

  1. /**
  2. * 在指定位置加入一个新的Item
  3. *
  4. * @param positionToAdd
  5. */
  6. public void addItem(int positionToAdd) {
  7. sampleData.add(positionToAdd, new SampleModel("新的列表项" + new Random().nextInt(10000)));
  8. // 通知RecyclerView控件插入了某个Item
  9. notifyItemInserted(positionToAdd);
  10. }

为RecyclerView加入item的点击事件

方法一:利用回调的方式实现(不太完好,仍可实现)

实现过程例如以下:

在adapter类中,定义接口,接口中定义两个方法分别相应click和longClick,定义完接口。加入接口和设置Adapter接口的方法:

  1. /**
  2. * 接口 ,提供两个方法
  3. */
  4. public interface OnRecyclerViewItemClickListener{
  5. // 单击事件
  6. void onItemClick(View view ,int position);
  7. // 长按触发的事件
  8. void onItemLongClick(View view ,int position);
  9. }
  10. // 定义OnRecyclerViewItemClickListener对象
  11. public OnRecyclerViewItemClickListener mOnRecyclerViewItemClickListener ;
  12. // 暴漏给外部的set方法。持有OnRecyclerViewItemClickListener对象
  13. public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener listener){
  14. this.mOnRecyclerViewItemClickListener = listener ;
  15. }

在onBindViewHolder方法中

  1. // 点击事件
  2. if(mOnRecyclerViewItemClickListener != null){
  3. // click
  4. holder.itemView.setOnClickListener(new View.OnClickListener() {
  5. @Override
  6. public void onClick(View v) {
  7. mOnRecyclerViewItemClickListener.onItemClick(holder.itemView,position);
  8. }
  9. });
  10. // longClick
  11. holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
  12. @Override
  13. public boolean onLongClick(View v) {
  14. mOnRecyclerViewItemClickListener.onItemLongClick(holder.itemView,position);
  15. return false;
  16. }
  17. });
  18. }

做完这些事情,我们就能够在Activity或其它地方为RecyclerView加入项目点击事件了,

  1. // 设置监事件
  2. sampleRecyclerAdapter.setOnRecyclerViewItemClickListener(new SampleRecyclerAdapter.OnRecyclerViewItemClickListener() {
  3. @Override
  4. public void onItemClick(View view, int position) {
  5. Toast.makeText(RecyclerViewAct.this,"Click" + position ,Toast.LENGTH_SHORT).show();
  6. }
  7. @Override
  8. public void onItemLongClick(View view, int position) {
  9. Toast.makeText(RecyclerViewAct.this,"LongClick" + position ,Toast.LENGTH_SHORT).show();
  10. }
  11. });

完整代码例如以下:

RecyclerViewAct

  1. package demo.turing.com.materialdesignwidget.recyclerView;
  2. import android.os.Bundle;
  3. import android.support.v7.app.AppCompatActivity;
  4. import android.support.v7.widget.DefaultItemAnimator;
  5. import android.support.v7.widget.LinearLayoutManager;
  6. import android.support.v7.widget.RecyclerView;
  7. import android.view.View;
  8. import android.widget.Toast;
  9. import demo.turing.com.materialdesignwidget.R;
  10. import demo.turing.com.materialdesignwidget.recyclerView.adapter.SampleRecyclerAdapter;
  11. public class RecyclerViewAct extends AppCompatActivity {
  12. @Override
  13. protected void onCreate(Bundle savedInstanceState) {
  14. super.onCreate(savedInstanceState);
  15. setContentView(R.layout.activity_recycler_view);
  16. // 获取RecyclerView对象
  17. RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recycler_view);
  18. // 创建线性布局管理器(默认是垂直方向)
  19. LinearLayoutManager layoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
  20. // 为RecyclerView指定布局管理对象
  21. recyclerView.setLayoutManager(layoutManager);
  22. // 创建列表项分隔线对象
  23. RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST);
  24. // 为RecyclerView控件指定分隔线对象
  25. recyclerView.addItemDecoration(itemDecoration);
  26. // 默认动画效果
  27. recyclerView.setItemAnimator(new DefaultItemAnimator());
  28. SampleRecyclerAdapter sampleRecyclerAdapter = new SampleRecyclerAdapter();
  29. recyclerView.setAdapter(sampleRecyclerAdapter);
  30. // 设置监事件
  31. sampleRecyclerAdapter.setOnRecyclerViewItemClickListener(new SampleRecyclerAdapter.OnRecyclerViewItemClickListener() {
  32. @Override
  33. public void onItemClick(View view, int position) {
  34. Toast.makeText(RecyclerViewAct.this,"Click" + position ,Toast.LENGTH_SHORT).show();
  35. }
  36. @Override
  37. public void onItemLongClick(View view, int position) {
  38. Toast.makeText(RecyclerViewAct.this,"LongClick" + position ,Toast.LENGTH_SHORT).show();
  39. }
  40. });
  41. }
  42. }

SampleRecyclerAdapter

  1. package demo.turing.com.materialdesignwidget.recyclerView.adapter;
  2. import android.support.v7.widget.RecyclerView;
  3. import android.view.LayoutInflater;
  4. import android.view.View;
  5. import android.view.ViewGroup;
  6. import android.widget.TextView;
  7. import java.util.ArrayList;
  8. import java.util.Random;
  9. import demo.turing.com.materialdesignwidget.R;
  10. import demo.turing.com.materialdesignwidget.recyclerView.SimulatorData;
  11. import demo.turing.com.materialdesignwidget.recyclerView.model.SampleModel;
  12. /**
  13. * MyApp
  14. *
  15. * @author Mr.Yang on 2016-03-30 21:03.
  16. * @version 1.0
  17. * @desc
  18. *
  19. *
  20. * RecyclerView 点击事件 请看http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1118/2004.html
  21. */
  22. public class SampleRecyclerAdapter extends RecyclerView.Adapter<SampleRecyclerAdapter.ViewHolder> {
  23. // 模拟数据
  24. private ArrayList<SampleModel> sampleData = SimulatorData.getSampleModelData(20);
  25. /**
  26. * 接口 ,提供两个方法
  27. */
  28. public interface OnRecyclerViewItemClickListener{
  29. // 单击事件
  30. void onItemClick(View view ,int position);
  31. // 长按触发的事件
  32. void onItemLongClick(View view ,int position);
  33. }
  34. // 定义OnRecyclerViewItemClickListener对象
  35. public OnRecyclerViewItemClickListener mOnRecyclerViewItemClickListener ;
  36. // 暴漏给外部的set方法。持有OnRecyclerViewItemClickListener对象
  37. public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener listener){
  38. this.mOnRecyclerViewItemClickListener = listener ;
  39. }
  40. /**
  41. * 用于创建控件
  42. *
  43. * @param parent
  44. * @param viewType
  45. * @return
  46. */
  47. @Override
  48. public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  49. // 获得列表项控件(LinearLayer对象)
  50. // list_basic_item.xml布局文件里仅仅包括一个<LinearLayer>标签,
  51. // 在该标签中包括了一个<TextView>标签, item是LinearLayout对象
  52. View item = LayoutInflater.from(parent.getContext()).inflate(
  53. R.layout.list_basic_item, parent, false);
  54. ViewHolder viewHolder = new ViewHolder(item);
  55. return viewHolder;
  56. }
  57. /**
  58. * 为控件设置数据
  59. *
  60. * @param holder
  61. * @param position
  62. */
  63. @Override
  64. public void onBindViewHolder(final ViewHolder holder, final int position) {
  65. // 获取当前item中显示的数据
  66. final SampleModel rowData = sampleData.get(position);
  67. // 设置要显示的数据
  68. holder.textViewSample.setText(rowData.getText());
  69. // 设置tag
  70. holder.itemView.setTag(rowData);
  71. // 点击事件
  72. if(mOnRecyclerViewItemClickListener != null){
  73. // click
  74. holder.itemView.setOnClickListener(new View.OnClickListener() {
  75. @Override
  76. public void onClick(View v) {
  77. // 通过getLayoutPosition,防止position错位
  78. int layoutPosition = holder.getLayoutPosition();
  79. mOnRecyclerViewItemClickListener.onItemClick(holder.itemView,layoutPosition);
  80. }
  81. });
  82. // longClick
  83. holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
  84. @Override
  85. public boolean onLongClick(View v) {
  86. int layoutPosition = holder.getLayoutPosition();
  87. mOnRecyclerViewItemClickListener.onItemLongClick(holder.itemView,layoutPosition);
  88. return false;
  89. }
  90. });
  91. }
  92. }
  93. @Override
  94. public int getItemCount() {
  95. return sampleData.size();
  96. }
  97. /**
  98. * 删除指定的Item
  99. *
  100. * @param position
  101. */
  102. public void removeData(int position) {
  103. sampleData.remove(position);
  104. // 通知RecyclerView控件某个Item已经被删除
  105. notifyItemRemoved(position);
  106. }
  107. /**
  108. * 在指定位置加入一个新的Item
  109. *
  110. * @param positionToAdd
  111. */
  112. public void addItem(int positionToAdd) {
  113. sampleData.add(positionToAdd, new SampleModel("新的列表项" + new Random().nextInt(10000)));
  114. // 通知RecyclerView控件插入了某个Item
  115. notifyItemInserted(positionToAdd);
  116. }
  117. /**
  118. * 相应Item中的控件
  119. */
  120. public static class ViewHolder extends RecyclerView.ViewHolder {
  121. private final TextView textViewSample;
  122. public ViewHolder(View itemView) {
  123. super(itemView);
  124. textViewSample = (TextView) itemView
  125. .findViewById(R.id.textViewSample);
  126. }
  127. }
  128. }

方法二:使用观察者模式实现

原理:

为RecyclerView的每一个子item设置setOnClickListener。然后在onClick中再调用一次对外封装的接口。将这个事件传递给外面的调用者。而“为RecyclerView的每一个子item设置setOnClickListener”在Adapter中设置。事实上直接在onClick中也能全然处理item的点击事件,可是这样会破坏代码的逻辑。

步骤

在自己定义的adapter(记得implements View.OnClickListener,以下有个onClick方法)中定义例如以下接口,模拟ListView的OnItemClickListener:

  1. //define interface
  2. public static interface OnRecyclerViewItemClickListener {
  3. void onItemClick(View view , String data);
  4. }

声明一个这个接口的变量:

  1. private OnRecyclerViewItemClickListener mOnItemClickListener = null;

在onCreateViewHolder()中为每一个item加入点击事件:

  1. @Override
  2. public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
  3. View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item, viewGroup, false);
  4. ViewHolder vh = new ViewHolder(view);
  5. //将创建的View注冊点击事件
  6. view.setOnClickListener(this);
  7. return vh;
  8. }

将点击事件转移给外面的调用者:

  1. @Override
  2. public void onClick(View v) {
  3. if (mOnItemClickListener != null) {
  4. //注意这里使用getTag方法获取数据
  5. mOnItemClickListener.onItemClick(v,(String)v.getTag());
  6. }
  7. }

意上面调用接口的onItemClick()中的v.getTag()方法,这须要在onBindViewHolder()方法中设置和item相关的数据

  1. @Override
  2. public void onBindViewHolder(ViewHolder viewHolder, int position) {
  3. viewHolder.mTextView.setText(datas[position]);
  4. //将数据保存在itemView的Tag中,以便点击时进行获取
  5. viewHolder.itemView.setTag(datas[position]);
  6. }

最后暴露给外面的调用者,定义一个设置Listener的方法():

  1. public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
  2. this.mOnItemClickListener = listener;
  3. }

以上全部步骤都发生在自己定义的adapter中,典型的观察者模式,有点绕的地方在于,这里涉及到两个观察者模式的使用,view的setOnClickListener本来就是观察者模式,我们将这个观察者模式的事件监听传递给了我们自己的观察者模式。

在Activity中使用

  1. mRecyclerView = (RecyclerView)findViewById(R.id.my_recycler_view);
  2. //创建默认的线性LayoutManager
  3. mLayoutManager = new LinearLayoutManager(this);
  4. mRecyclerView.setLayoutManager(mLayoutManager);
  5. //假设能够确定每一个item的高度是固定的,设置这个选项能够提高性能
  6. mRecyclerView.setHasFixedSize(true);
  7. //创建并设置Adapter
  8. mAdapter = new MyAdapter(data);
  9. mRecyclerView.setAdapter(mAdapter);
  10. mAdapter.setOnItemClickListener(new OnRecyclerViewItemClickListener(){
  11. @Override
  12. public void onItemClick(View view , String data){
  13. Toast.makeText(MainActivity.this, data, 600).show();
  14. }
  15. });

~

RecyclerView加入Header

。。。。。。

RecyclerView的那点事儿的更多相关文章

  1. RecyclerView再封装

    RecyclerView做为ListView的替代品,已经出了很久了,既然是替代品,那自然有些ListView没有的优点.比如说:可以随意切换list,grid,stagger.可以指定一个或多个it ...

  2. 说说Makefile那些事儿

    说说Makefile那些事儿 |扬说|透过现象看本质 工作至今,一直对Makefile半知半解.突然某天幡然醒悟,觉得此举极为不妥,只得洗心革面从头学来,以前许多不明觉厉之处顿时茅塞顿开,想想好记性不 ...

  3. RecyclerView使用大全

    RecylerView介绍 RecylerView是support-v7包中的新组件,是一个强大的滑动组件,与经典的ListView相比,同样拥有item回收复用的功能,这一点从它的名字recyler ...

  4. 带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载

    title: 带你实现开发者头条APP(五)--RecyclerView下拉刷新上拉加载 tags: -RecyclerView,下拉刷新,上拉加载更多 grammar_cjkRuby: true - ...

  5. 安卓易学,爬坑不易——腾讯老司机的RecyclerView局部刷新爬坑之路

    针对手游的性能优化,腾讯WeTest平台的Cube工具提供了基本所有相关指标的检测,为手游进行最高效和准确的测试服务,不断改善玩家的体验.目前功能还在免费开放中. 点击地址:http://wetest ...

  6. Android Studio开发RecyclerView遇到的各种问题以及解决(二)

    开发RecyclerView时候需要导入别人的例子,我的是从github导入的,下载下github的压缩包之后解压看你要导入的文件是priject还是Module.(一般有app文件夹的大部分是pro ...

  7. Android Studio开发RecyclerView遇到的各种问题以及解决(一)

    以前一直在用ListView,,,最近才看RecyclerView发现好强大.RecyclerView前提是Android版本在5.0以上,本人以前用的是eclipse只支持到4.4.索性就安装一个A ...

  8. Android的Kotlin秘方(II):RecyclerView 和 DiffUtil

    作者:Antonio Leiva 时间:Sep 12, 2016 原文链接:http://antonioleiva.com/recyclerview-diffutil-kotlin/ 如你所知,在[支 ...

  9. 总结iOS开发中的断点续传那些事儿

    前言 断点续传概述 断点续传就是从文件赏赐中断的地方重新开始下载或者上传数据,而不是从头文件开始.当下载大文件的时候,如果没有实现断点续传功能,那么每次出现异常或者用户主动的暂停,都会从头下载,这样很 ...

随机推荐

  1. Flask获取post提交数据

    完成示例 # flask 代码 from flask import Flask,request ... @app.route('/get_tasks',methods=["POST" ...

  2. SharePoint 2013 Custom MasterPage

    <%@Master language="C#"%> <%@ Register Tagprefix="SharePoint" Namespace ...

  3. 【CF1020C】Elections(贪心)

    题意: Berland地区的腐败现象非常常见. 马上有一场选举,你事先知道了选民和政党的数量,分别为 n 和 m ,对于每一位选民,你知道他将要选举哪一个政党, 不过,每一位选民都会在接受一定数额的金 ...

  4. mybatis传入map参数,map中包含list(输入参数)

    1.xml中配置: <!-- 根据条件查询满足条件的ID集合开始 --> <select id="getQuestionsIdsForExamPaper" res ...

  5. Django ConnectionAbortedError WinError 10053 错误

    因为ajax默认是异步提交,可是有时候我们会发现,本来要求请求马上出现,可是异步会导致后面突然再执行,这样就出问题了. (1)添加这样一段代码 $.ajaxSetup({ async : false ...

  6. Linux 之 Redis

    Linux 之 Redis 参考教程:[千峰教育] 一.Redis简介: 说明: 1.也是一种类似于Memcached的key-value机制的存储服务 2.是非关系型数据库(NoSQL)的一种 3. ...

  7. vSphere Client 更改 ESX/ESXi 主机的端口

    https://blog.csdn.net/hanzheng260561728/article/details/51283808?locationNum=8&fps=1

  8. 基于python的性能测试工具–locust

    现在有很多的性能测试工具,比如说我们熟悉的loadrunner.jmeter.ab.webbench等等,这些工具如果对一个没用过的朋友来说,学习起来比较不容易,但是如果你能看懂python代码,会写 ...

  9. 51 Nod 1238 最小公倍数之和 V3 杜教筛

    题目链接:http://www.51nod.com/Challenge/Problem.html#!#problemId=1238 题意:求$\sum_{i=1}^{n}\sum_{j=1}^{n}l ...

  10. Codeforces 235 C

    题目大意 给定一个模板串, 再给出\(n\)个询问, 询问每一个串的循环串总共在原串中出现了多少次. 循环串: 比如说有\(str[] = \{ABCD\}\), 则其循环串有\(\{ABCD\}, ...