[关闭]
@hx 2018-04-27T14:12:03.000000Z 字数 13261 阅读 928

RecyclerView

Android


提供三种内置LayoutManager

LinearLayoutManager:线性布局,横向或者纵向滑动列表
GridLayoutManager:表格布局
StaggeredGridLayoutManager:流式布局,例如瀑布流效果

常用类

1.主布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:orientation="vertical">
  7. <android.support.v7.widget.RecyclerView
  8. android:id="@+id/recycler_view"
  9. android:layout_width="match_parent"
  10. android:scrollbars="horizontal"
  11. android:layout_height="match_parent">
  12. </android.support.v7.widget.RecyclerView>
  13. </LinearLayout>

2.子布局

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <FrameLayout
  3. xmlns:android="http://schemas.android.com/apk/res/android"
  4. android:layout_width="match_parent"
  5. android:layout_height="72dp"
  6. android:layout_margin="1dp"
  7. android:background="@color/colorLine">
  8. <TextView
  9. android:id="@+id/second_text_view"
  10. android:layout_width="72dp"
  11. android:layout_height="match_parent"
  12. android:gravity="center"
  13. android:text="A"
  14. android:textSize="24sp"/>
  15. </FrameLayout>

3-1.Adapter

  1. public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder> {
  2. private Context mContext;
  3. private List<String> mList;
  4. private LayoutInflater mLayoutInflater;
  5. public MyRecyclerViewAdapter(Context context, List<String> list) {
  6. mContext = context;
  7. mList = list;
  8. mLayoutInflater = LayoutInflater.from(context);
  9. }
  10. // 创建ViewHolder
  11. @Override
  12. public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  13. View view = mLayoutInflater.inflate(R.layout.item, parent, false);
  14. MyViewHolder myViewHolder = new MyViewHolder(view);
  15. return myViewHolder;
  16. }
  17. @Override
  18. public void onBindViewHolder(MyViewHolder holder, int position) {
  19. holder.mTextView.setText(mList.get(position));
  20. }
  21. @Override
  22. public int getItemCount() {
  23. return mList.size();
  24. }
  25. class MyViewHolder extends RecyclerView.ViewHolder {
  26. TextView mTextView;
  27. public MyViewHolder(View itemView) {
  28. super(itemView);
  29. mTextView = (TextView) itemView.findViewById(R.id.second_text_view);
  30. }
  31. }
  32. }

3-2.瀑布流 StaggeredAdapter

  1. public class StaggeredAdapter extends RecyclerView.Adapter<StaggeredAdapter.MyViewHolder> {
  2. private Context mContext;
  3. private List<String> mList;
  4. private LayoutInflater mLayoutInflater;
  5. // 自定义Item高度
  6. private List<Integer> mHeight;
  7. public StaggeredAdapter(Context context, List<String> list) {
  8. mContext = context;
  9. mList = list;
  10. mLayoutInflater = LayoutInflater.from(context);
  11. mHeight = new ArrayList<>();
  12. // 随机高度
  13. for (int i = 0; i < mList.size(); i++) {
  14. mHeight.add((int) (100 + Math.random() * 300));
  15. }
  16. }
  17. // 创建ViewHolder
  18. @Override
  19. public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  20. View view = mLayoutInflater.inflate(R.layout.item, parent, false);
  21. MyViewHolder myViewHolder = new MyViewHolder(view);
  22. return myViewHolder;
  23. }
  24. @Override
  25. public void onBindViewHolder(MyViewHolder holder, int position) {
  26. // 获取Item 父布局高度
  27. ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
  28. layoutParams.height = mHeight.get(position);
  29. // 设置Item 父布局高度
  30. holder.itemView.setLayoutParams(layoutParams);
  31. holder.mTextView.setText(mList.get(position));
  32. }
  33. @Override
  34. public int getItemCount() {
  35. return mList.size();
  36. }
  37. class MyViewHolder extends RecyclerView.ViewHolder {
  38. TextView mTextView;
  39. public MyViewHolder(View itemView) {
  40. super(itemView);
  41. mTextView = (TextView) itemView.findViewById(R.id.second_text_view);
  42. }
  43. }
  44. }

4-1. MainActivity

  1. public class SecondActivity extends AppCompatActivity {
  2. private List<String> mList;
  3. private RecyclerView mRecyclerView;
  4. @Override
  5. protected void onCreate(@Nullable Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.activity_second);
  8. initViews();
  9. initDatas();
  10. MyRecyclerViewAdapter myRecyclerViewAdapter = new MyRecyclerViewAdapter(this, mList);
  11. mRecyclerView.setAdapter(myRecyclerViewAdapter);
  12. // 设置Recycler的布局方法
  13. LinearLayoutManager linearLayoutManager =
  14. new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
  15. mRecyclerView.setLayoutManager(linearLayoutManager);
  16. // 设置Item间分割线
  17. // mRecyclerView.addItemDecoration(new DividerItemDecoration(
  18. // this, DividerItemDecoration.VERTICAL_LIST));
  19. }
  20. private void initViews() {
  21. mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
  22. }
  23. private void initDatas() {
  24. mList = new ArrayList<>();
  25. for (int i = 'A'; i < 'Z'; i++) {
  26. mList.add("" + (char) i);
  27. }
  28. }
  29. @Override
  30. public boolean onCreateOptionsMenu(Menu menu) {
  31. getMenuInflater().inflate(R.menu.menu_main2, menu);
  32. return true;
  33. }
  34. @Override
  35. public boolean onOptionsItemSelected(MenuItem item) {
  36. int id = item.getItemId();
  37. switch (id) {
  38. case R.id.action_list:
  39. mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
  40. break;
  41. case R.id.action_gridView:
  42. mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
  43. break;
  44. case R.id.action_horizontalView:
  45. mRecyclerView.setLayoutManager(
  46. new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
  47. break;
  48. case R.id.action_staggered:
  49. startActivity(new Intent(SecondActivity.this, StaggeredActivity.class));
  50. break;
  51. case R.id.action_HorizontalGridView:
  52. mRecyclerView.setLayoutManager(
  53. new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.HORIZONTAL));
  54. break;
  55. default:
  56. break;
  57. }
  58. return super.onOptionsItemSelected(item);
  59. }
  60. }

4-2. StaggeredActivity

  1. public class StaggeredActivity extends AppCompatActivity {
  2. private List<String> mList;
  3. private RecyclerView mRecyclerView;
  4. @Override
  5. protected void onCreate(@Nullable Bundle savedInstanceState) {
  6. super.onCreate(savedInstanceState);
  7. setContentView(R.layout.activity_second);
  8. initViews();
  9. initDatas();
  10. StaggeredAdapter Staggered = new StaggeredAdapter(this, mList);
  11. mRecyclerView.setAdapter(Staggered);
  12. // 设置Recycler的布局方法
  13. mRecyclerView.setLayoutManager(
  14. new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL));
  15. }
  16. private void initViews() {
  17. mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
  18. }
  19. private void initDatas() {
  20. mList = new ArrayList<>();
  21. for (int i = 'A'; i <= 'Z'; i++) {
  22. mList.add("" + (char) i);
  23. }
  24. }
  25. }

5-1.普通分割线

  1. public class DividerItemDecoration extends RecyclerView.ItemDecoration {
  2. private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
  3. public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
  4. public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
  5. private Drawable mDivider;
  6. private int mOrientation;
  7. public DividerItemDecoration(Context context, int orientation) {
  8. final TypedArray a = context.obtainStyledAttributes(ATTRS);
  9. mDivider = a.getDrawable(0);
  10. a.recycle();
  11. setOrientation(orientation);
  12. }
  13. public void setOrientation(int orientation) {
  14. if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
  15. throw new IllegalArgumentException("invalid orientation");
  16. }
  17. mOrientation = orientation;
  18. }
  19. @Override
  20. public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
  21. if (mOrientation == VERTICAL_LIST) {
  22. drawVertical(c, parent);
  23. } else {
  24. drawHorizontal(c, parent);
  25. }
  26. }
  27. public void drawVertical(Canvas c, RecyclerView parent) {
  28. final int left = parent.getPaddingLeft();
  29. final int right = parent.getWidth() - parent.getPaddingRight();
  30. final int childCount = parent.getChildCount();
  31. for (int i = 0; i < childCount; i++) {
  32. final View child = parent.getChildAt(i);
  33. RecyclerView v = new RecyclerView(
  34. parent.getContext());
  35. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
  36. .getLayoutParams();
  37. final int top = child.getBottom() + params.bottomMargin;
  38. final int bottom = top + mDivider.getIntrinsicHeight();
  39. mDivider.setBounds(left, top, right, bottom);
  40. mDivider.draw(c);
  41. }
  42. }
  43. public void drawHorizontal(Canvas c, RecyclerView parent) {
  44. final int top = parent.getPaddingTop();
  45. final int bottom = parent.getHeight() - parent.getPaddingBottom();
  46. final int childCount = parent.getChildCount();
  47. for (int i = 0; i < childCount; i++) {
  48. final View child = parent.getChildAt(i);
  49. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
  50. .getLayoutParams();
  51. final int left = child.getRight() + params.rightMargin;
  52. final int right = left + mDivider.getIntrinsicHeight();
  53. mDivider.setBounds(left, top, right, bottom);
  54. mDivider.draw(c);
  55. }
  56. }
  57. @Override
  58. public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
  59. super.getItemOffsets(outRect, view, parent, state);
  60. if (mOrientation == VERTICAL_LIST) {
  61. outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
  62. } else {
  63. outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
  64. }
  65. }
  66. }

5-2. Grid分隔线

  1. public class DividerGridItemDecoration extends RecyclerView.ItemDecoration {
  2. private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
  3. private Drawable mDivider;
  4. public DividerGridItemDecoration(Context context) {
  5. final TypedArray a = context.obtainStyledAttributes(ATTRS);
  6. mDivider = a.getDrawable(0);
  7. a.recycle();
  8. }
  9. @Override
  10. public void onDraw(Canvas c, RecyclerView parent, State state) {
  11. drawHorizontal(c, parent);
  12. drawVertical(c, parent);
  13. }
  14. private int getSpanCount(RecyclerView parent) {
  15. // 列数
  16. int spanCount = -1;
  17. LayoutManager layoutManager = parent.getLayoutManager();
  18. if (layoutManager instanceof GridLayoutManager) {
  19. spanCount = ((GridLayoutManager) layoutManager).getSpanCount();
  20. } else if (layoutManager instanceof StaggeredGridLayoutManager) {
  21. spanCount = ((StaggeredGridLayoutManager) layoutManager)
  22. .getSpanCount();
  23. }
  24. return spanCount;
  25. }
  26. public void drawHorizontal(Canvas c, RecyclerView parent) {
  27. int childCount = parent.getChildCount();
  28. for (int i = 0; i < childCount; i++) {
  29. final View child = parent.getChildAt(i);
  30. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
  31. .getLayoutParams();
  32. final int left = child.getLeft() - params.leftMargin;
  33. final int right = child.getRight() + params.rightMargin
  34. + mDivider.getIntrinsicWidth();
  35. final int top = child.getBottom() + params.bottomMargin;
  36. final int bottom = top + mDivider.getIntrinsicHeight();
  37. mDivider.setBounds(left, top, right, bottom);
  38. mDivider.draw(c);
  39. }
  40. }
  41. public void drawVertical(Canvas c, RecyclerView parent) {
  42. final int childCount = parent.getChildCount();
  43. for (int i = 0; i < childCount; i++) {
  44. final View child = parent.getChildAt(i);
  45. final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
  46. .getLayoutParams();
  47. final int top = child.getTop() - params.topMargin;
  48. final int bottom = child.getBottom() + params.bottomMargin;
  49. final int left = child.getRight() + params.rightMargin;
  50. final int right = left + mDivider.getIntrinsicWidth();
  51. mDivider.setBounds(left, top, right, bottom);
  52. mDivider.draw(c);
  53. }
  54. }
  55. private boolean isLastColum(RecyclerView parent, int pos, int spanCount,
  56. int childCount) {
  57. LayoutManager layoutManager = parent.getLayoutManager();
  58. if (layoutManager instanceof GridLayoutManager) {
  59. if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
  60. {
  61. return true;
  62. }
  63. } else if (layoutManager instanceof StaggeredGridLayoutManager) {
  64. int orientation = ((StaggeredGridLayoutManager) layoutManager)
  65. .getOrientation();
  66. if (orientation == StaggeredGridLayoutManager.VERTICAL) {
  67. if ((pos + 1) % spanCount == 0)// 如果是最后一列,则不需要绘制右边
  68. {
  69. return true;
  70. }
  71. } else {
  72. childCount = childCount - childCount % spanCount;
  73. if (pos >= childCount)// 如果是最后一列,则不需要绘制右边
  74. return true;
  75. }
  76. }
  77. return false;
  78. }
  79. private boolean isLastRaw(RecyclerView parent, int pos, int spanCount,
  80. int childCount) {
  81. LayoutManager layoutManager = parent.getLayoutManager();
  82. if (layoutManager instanceof GridLayoutManager) {
  83. childCount = childCount - childCount % spanCount;
  84. if (pos >= childCount)// 如果是最后一行,则不需要绘制底部
  85. return true;
  86. } else if (layoutManager instanceof StaggeredGridLayoutManager) {
  87. int orientation = ((StaggeredGridLayoutManager) layoutManager)
  88. .getOrientation();
  89. // StaggeredGridLayoutManager 且纵向滚动
  90. if (orientation == StaggeredGridLayoutManager.VERTICAL) {
  91. childCount = childCount - childCount % spanCount;
  92. // 如果是最后一行,则不需要绘制底部
  93. if (pos >= childCount)
  94. return true;
  95. } else
  96. // StaggeredGridLayoutManager 且横向滚动
  97. {
  98. // 如果是最后一行,则不需要绘制底部
  99. if ((pos + 1) % spanCount == 0) {
  100. return true;
  101. }
  102. }
  103. }
  104. return false;
  105. }
  106. @Override
  107. public void getItemOffsets(Rect outRect, int itemPosition,
  108. RecyclerView parent) {
  109. int spanCount = getSpanCount(parent);
  110. int childCount = parent.getAdapter().getItemCount();
  111. if (isLastRaw(parent, itemPosition, spanCount, childCount))// 如果是最后一行,则不需要绘制底部
  112. {
  113. outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
  114. } else if (isLastColum(parent, itemPosition, spanCount, childCount))// 如果是最后一列,则不需要绘制右边
  115. {
  116. outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
  117. } else {
  118. outRect.set(0, 0, mDivider.getIntrinsicWidth(),
  119. mDivider.getIntrinsicHeight());
  120. }
  121. }
  122. }

6.设置Item动画
MyRecyclerViewAdapter中添加2个方法,然后在MainActivity中设置动画

  1. // 创建添加方法
  2. public void addData(int position) {
  3. mList.add(position, "Insert one");
  4. notifyItemInserted(position);
  5. }
  6. // 创建remove方法
  7. public void removeDate(int position) {
  8. mList.remove(position);
  9. notifyItemRemoved(position);
  10. }
  1. public boolean onOptionsItemSelected(MenuItem item) {
  2. int id = item.getItemId();
  3. switch (id) {
  4. case R.id.action_add:
  5. mMyRecyclerViewAdapter.addData(1);
  6. break;
  7. case R.id.action_delete:
  8. mMyRecyclerViewAdapter.removeDate(1);
  9. break;

7.设置点击和长按事件
MyRecyclerViewAdapter中创建接口,并在onBindViewHolder()方法中设置点击和长按事件,然后在MainActivity中添加代码。

  1. // 创建接口
  2. public interface OnItemClickListener {
  3. void OnItemClick(View view, int position);
  4. void OnItemLongClick(View view, int position);
  5. }
  6. private OnItemClickListener mOnItemClickListener;
  7. public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
  8. this.mOnItemClickListener = onItemClickListener;
  9. }
  10. @Override
  11. public void onBindViewHolder(final MyViewHolder holder, final int position) {
  12. holder.mTextView.setText(mList.get(position));
  13. if (mOnItemClickListener != null) {
  14. // 点击
  15. holder.itemView.setOnClickListener(new View.OnClickListener() {
  16. @Override
  17. public void onClick(View view) {
  18. int layoutPosition = holder.getLayoutPosition();
  19. mOnItemClickListener.OnItemClick(holder.itemView, layoutPosition);
  20. }
  21. }
  22. });
  23. // 长按
  24. holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
  25. int layoutPosition = holder.getLayoutPosition();
  26. @Override
  27. public boolean onLongClick(View view) {
  28. mOnItemClickListener.OnItemLongClick(holder.itemView, layoutPosition);
  29. return true;
  30. }
  31. });
  32. }
  33. }
  1. // 设置点击和长击事件
  2. mMyRecyclerViewAdapter.setOnItemClickListener(new MyRecyclerViewAdapter.OnItemClickListener() {
  3. @Override
  4. public void OnItemClick(View view, int position) {
  5. TextView textView = (TextView) view.findViewById(R.id.second_text_view);
  6. Toast.makeText(
  7. SecondActivity.this, "点击" + textView.getText() + "位置" + position, Toast.LENGTH_SHORT).show();
  8. }
  9. @Override
  10. public void OnItemLongClick(View view, int position) {
  11. Toast.makeText(
  12. SecondActivity.this, "长按第" + position, Toast.LENGTH_SHORT).show();
  13. }
  14. });

演示视频

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注