一、为什么叫做RecyclerView?
1、不关心Item是否显示在正确的位置,如何显示;(LayoutManager)
2、不关心Item间如何分割;(ItemDecoration)
3、不关注Item增加与删除的动画效果;(ItemAnimator)
4、仅仅关注如何回收与复用View。
(1)通过设置LayoutManager的不同实例来设计RecyclerView的风格;
(2)通过设置ItemDecoration来设计RecyclerView的分割方式;
(3)通过设置ItemAnimator来设计RecyclerView的动画效果。
二、与RecyclerView相关的重要类
1、Adapter
2、ViewHolder
3、LayoutManager
4、ItemDecoration
5、ItemAnimator
三、RecyclerView能干什么?
1、ListView(LayoutManager)
2、GridView(LayoutManager)
3、横向ListView(LayoutManager)
4、横向GridView(LayoutManager)
5、瀑布流(LayoutManager)
6、定制Item增加与删除动画(ItemAnimator)
(1)实现ListView
1>写布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.qf.day_03.Main3Activity"><android.support.v7.widget.RecyclerViewandroid:id="@+id/id_recyclerview"android:layout_width="match_parent"android:layout_height="match_parent"></android.support.v7.widget.RecyclerView></RelativeLayout>
2>查找控件
private void initViews() { mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); } 3>获取数据
private void initDatas() {mDatas = new ArrayList<>();for (int i = 'A'; i <'z' ; i++) {mDatas.add("" + (char) i);}}
4>自定义适配器
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;/*** 适配器*/public class SimpleAdapter extends RecyclerView.Adapter<MyViewHolder> {private LayoutInflater mInflater;private Context mContext;private List<String> mDatas;public SimpleAdapter(Context context, List<String> datas) {mContext = context;mDatas = datas;mInflater=LayoutInflater.from(mContext);}/*** 创建ViewHolder* @param parent* @param viewType* @return*/@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View mView = mInflater.inflate(R.layout.item_single, parent, false);MyViewHolder mViewHolder = new MyViewHolder(mView);return mViewHolder;}/*** 绑定数据* @param holder* @param position*/@Overridepublic void onBindViewHolder(MyViewHolder holder, int position) {holder.mTextView.setText(mDatas.get(position));}/*** 返回条目数* @return*/@Overridepublic int getItemCount() {return mDatas.size();}}class MyViewHolder extends RecyclerView.ViewHolder{TextView mTextView;public MyViewHolder(View itemView) {super(itemView);mTextView= (TextView) itemView.findViewById(R.id.id_tv);}}
5>写Item布局文件
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:background="#4f00"android:layout_height="72dp"><TextViewandroid:id="@+id/id_tv"android:gravity="center"android:layout_width="match_parent"android:layout_height="match_parent"/></FrameLayout>
6>设置适配器
mAdapter = new SimpleAdapter(this, mDatas); mRecyclerView.setAdapter(mAdapter);
7>为RecyclerView设置布局管理
//设置RecyclerView的布局管理 mRecyclerView.setLayoutManager(new LinearLayoutManager(Main3Activity.this,LinearLayoutManager.VERTICAL,false));
8>为RecyclerView的Item设置分割线
//设置RecyclerView的Item间的分割线 mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST));
9>设置RecyclerView的Item间分割线的类
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;/*** 设置RecyclerView的Item之间间隔的类*/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;}@Overridepublic 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);}}@Overridepublic 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);}}}
10>秒变GridView
mRecyclerView.setLayoutManager(new GridLayoutManager(Main3Activity.this,3));//mRecyclerView.setLayoutManager(new GridLayoutManager(this,3,GridLayoutManager.HORIZONTAL,false));
(2)实现瀑布流布局
1>写布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context="com.qf.day_03.Main3Activity"><android.support.v7.widget.RecyclerViewandroid:id="@+id/id_recyclerview"android:layout_width="match_parent"android:layout_height="match_parent"></android.support.v7.widget.RecyclerView></RelativeLayout>
2>查找控件
private void initViews() { mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview); } 3>获取数据
private void initDatas() {mDatas = new ArrayList<>();for (int i = 'A'; i <'z' ; i++) {mDatas.add("" + (char) i);}}
4>自定义适配器
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.ArrayList;import java.util.List;/*** 瀑布流适配器*/public class StaggeredAdapter extends RecyclerView.Adapter<StaggeredAdapter.MyViewHolder>{private LayoutInflater mInflater;private Context mContext;private List<String> mDatas;private List<Integer> mHeights;public StaggeredAdapter(Context context, List<String> datas) {mContext = context;mDatas = datas;mInflater=LayoutInflater.from(mContext);mHeights = new ArrayList<>();for (int i = 0; i < mDatas.size(); i++) {mHeights.add((int) (100 + Math.random() * 300));}}/*** 创建ViewHolder* @param parent* @param viewType* @return*/@Overridepublic MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {View mView = mInflater.inflate(R.layout.item_single, parent, false);MyViewHolder mViewHolder = new MyViewHolder(mView);return mViewHolder;}/*** 绑定数据* @param holder* @param position*/@Overridepublic void onBindViewHolder(MyViewHolder holder, int position) {ViewGroup.LayoutParams mParams = holder.itemView.getLayoutParams();mParams.height = mHeights.get(position);holder.itemView.setLayoutParams(mParams);holder.mTextView.setText(mDatas.get(position));}/*** 返回条目数* @return*/@Overridepublic int getItemCount() {return mDatas.size();}class MyViewHolder extends RecyclerView.ViewHolder{TextView mTextView;public MyViewHolder(View itemView) {super(itemView);mTextView= (TextView) itemView.findViewById(R.id.id_tv);}}}
5>写Item布局文件
<?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:background="#4f00"android:layout_height="72dp"><TextViewandroid:id="@+id/id_tv"android:gravity="center"android:layout_width="match_parent"android:layout_height="match_parent"/></FrameLayout>
6>设置适配器
mAdapter = new StaggeredAdapter(this, mDatas); mRecyclerView.setAdapter(mAdapter);
7>为RecyclerView设置布局管理
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));
(3)增加和删除Item的动画
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
(4)设置Item监听事件
4.1>在适配器中定义点击事件的接口
/*** 设置点击事件的接口*/public interface OnItemClickListener{void onItemClick(View view, int position);void onItemLongClick(View view,int position);}private OnItemClickListener mOnItemClickListener;public void setOnItemClickListener(OnItemClickListener listener) {this.mOnItemClickListener = listener;}
4.2>在适配器的onBindViewHolder方法中设置Item的点击事件
if (mOnItemClickListener != null) {holder.itemView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//获取布局上的位置int mPosition = holder.getLayoutPosition();mOnItemClickListener.onItemClick(holder.itemView,mPosition);}});//longclickholder.itemView.setOnLongClickListener(new View.OnLongClickListener() {@Overridepublic boolean onLongClick(View v) {//获取布局上的位置(在有Item增加和减少的时候有用)int mPosition = holder.getLayoutPosition();mOnItemClickListener.onItemLongClick(holder.itemView,mPosition);return false;}});}
4.3>在Activity中为适配器设置点击事件
mAdapter.setOnItemClickListener(new SimpleAdapter.OnItemClickListener() {@Overridepublic void onItemClick(View view, int position) {Toast.makeText(Main3Activity.this, "click:"+position, Toast.LENGTH_SHORT).show();}@Overridepublic void onItemLongClick(View view, int position) {Toast.makeText(Main3Activity.this, "longclick:"+position, Toast.LENGTH_SHORT).show();}});
四、注意事项
1、ItemAnimator在使用的时候,不要使用notifyItemChanged(),而是要使用notifyItemInserted();和notifyItemMoved();。
2、RecyclerView没有提供Item的Click事件,所以需要手动在Adapter中提供ItemClick/longClick的回调。
3、RecyclerView可以实现在ListView、GridView、横向ListView、横向 GridView、瀑布流之间的灵活切换。