RecyclerView是一种新的视图组,目标是为任何给予适配器的视图提供相似的渲染方式,被作为ListView和GridView的继承者更加强大,大家可以通过导入support-v7对其进行使用。
如果使用RecyclerView,你需要了解以下三个元素:
还有一点:点击和长按事件,需要自己实现
使用方法如下:
content_main.xml
<android.support.v7.widget.RecyclerView android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="match_parent" />
content_item.xml
<TextView android:id="@+id/letter" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:text="1" />
MainActivity.java
package com.jackie.recyclerview; import android.content.Context; import android.os.Bundle; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.StaggeredGridLayoutManager; import android.support.v7.widget.Toolbar; import android.view.View; import android.widget.Toast; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private Context mContext; private List<String> mList; private RecyclerView mRecyclerView; private RecyclerViewAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) .setAction("Action", null).show(); } }); mContext = this; initData(); mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview); //1.设置布局管理器 // mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); //线性管理器,支持横向、纵向 //纵向的GridView,可以纵向滑动 // mRecyclerView.setLayoutManager(new GridLayoutManager(this, 4)); //网格布局管理器,第二个参数为列 //横向的GridView,可以横向滑动 // mRecyclerView.setLayoutManager(new GridLayoutManager(this, 4, GridLayoutManager.HORIZONTAL, false)); //网格布局管理器,第二个参数为行 /** * StaggeredGridLayoutManager构造的第二个参数传一个orientation, * 如果传入的是StaggeredGridLayoutManager.VERTICAL代表有多少列,可以纵向滑动 * 那么传入的如果是StaggeredGridLayoutManager.HORIZONTAL就代表有多少行,可以横向滑动 */ mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL)); // 瀑布式布局管理器 //2.设置Adapter mAdapter = new RecyclerViewAdapter(mContext, mList); mRecyclerView.setAdapter(mAdapter); mAdapter.setOnItemClickListener(new RecyclerViewAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(MainActivity.this, position + " short click", Toast.LENGTH_SHORT).show(); mAdapter.addItem(position); } @Override public void onItemLongClick(View view, int position) { Toast.makeText(MainActivity.this, position + " long click", Toast.LENGTH_SHORT).show(); mAdapter.removeItem(position); } }); //3.添加分割线 // mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST)); mRecyclerView.addItemDecoration(new DividerGridItemDecoration(this, 30)); //4.设置item动画 mRecyclerView.setItemAnimator(new DefaultItemAnimator()); } private void initData() { mList = new ArrayList<String>(); for (int i = 'A'; i < 'z'; i++) { mList.add("" + (char) i); } } }
RecyclerViewAdapter.java
package com.jackie.recyclerview; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import java.util.List; import java.util.Random; public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.RecycleViewHolder> { private Context mContext; private List<String> mList; public RecyclerViewAdapter(Context context, List<String> list) { this.mContext = context; this.mList = list; } public interface OnItemClickListener { void onItemClick(View view, int position); void onItemLongClick(View view , int position); } private OnItemClickListener onItemClickListener; public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } @Override public RecyclerViewAdapter.RecycleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { RecycleViewHolder holder = new RecycleViewHolder(LayoutInflater.from(mContext).inflate(R.layout.content_item, parent, false)); return holder; } @Override public void onBindViewHolder(final RecyclerViewAdapter.RecycleViewHolder holder, int position) { // 如果设置了回调,则设置点击事件 if (onItemClickListener != null) { holder.tv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onItemClickListener.onItemClick(holder.itemView, holder.getLayoutPosition()); } }); holder.tv.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { onItemClickListener.onItemLongClick(holder.itemView, holder.getLayoutPosition()); return false; } }); } holder.tv.setWidth(new Random().nextInt(400) + 100); //随机产生100到500的随机整数 holder.tv.setHeight(new Random().nextInt(400) + 100); holder.tv.setText(mList.get(position)); } @Override public int getItemCount() { return mList.size(); } public class RecycleViewHolder extends RecyclerView.ViewHolder { TextView tv; public RecycleViewHolder(View itemView) { super(itemView); tv = (TextView) itemView.findViewById(R.id.letter); } } /** * 注意,这里更新数据集不是用adapter.notifyDataSetChanged()而是 notifyItemInserted(position)与notifyItemRemoved(position) * @param position */ public void addItem(int position) { mList.add(position, "Insert"); notifyItemInserted(position); } public void removeItem(int position) { mList.remove(position); notifyItemRemoved(position); } }
DividerItemDecoration.java
package com.jackie.recyclerview; /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * limitations under the License. */ 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.util.Log; import android.view.View; /** * This class is from the v7 samples of the Android SDK. It's not by me! * <p/> * See the license above for details. */ 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) { Log.v("recyclerview - itemdecoration", "onDraw()"); 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); } } }
DividerGridItemDecoration.java
package com.jackie.recyclerview; 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; private int mSpace; public DividerGridItemDecoration(Context context, int space) { final TypedArray a = context.obtainStyledAttributes(ATTRS); mDivider = a.getDrawable(0); mSpace = space; 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 isLastColumn(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 isLastRow(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 (isLastRow(parent, itemPosition, spanCount, childCount)) { // 如果是最后一行,则不需要绘制底部 outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } else if (isLastColumn(parent, itemPosition, spanCount, childCount)) { // 如果是最后一列,则不需要绘制右边 outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), mDivider.getIntrinsicHeight()); } //设置间距 outRect.left = outRect.right = outRect.bottom = mSpace; } }效果图如下: