zoukankan      html  css  js  c++  java
  • RecyclerView的使用

    什么是RecyclerView
            RecyclerView是Android 5.0 materials design中的组件之一,相应的还有CardView、Palette等。看名字我们就能看出一点端倪,没错,它主要的特点就是复用。我们知道,Listview中的Adapter中可以实现ViewHolder的复用。RecyclerView提供了一个耦合度更低的方式来复用ViewHolder,并且可以轻松的实现ListView、GridView以及瀑布流的效果。
     
    RecyclerView的用法
            首先我们要gradle的依赖库中添加  compile 'com.android.support:recyclerview-v7:21.+'  。如果是eclipse直接导入android-support-v7-recyclerview.jar就可以了。
     1 /**
     2 * 设置Adapter
     3 */
     4 mRecyclerView.setAdapter(mListAdapter);
     5 /**
     6 * 设置布局管理器
     7 */
     8 mRecyclerView.setLayoutManager(linearLayoutManager);
     9 /**
    10 * 设置item分割线
    11 */
    12 mRecyclerView.addItemDecoration(itemDecoration);
    13 /**
    14 * 设置item动画
    15 */
    16 mRecyclerView.setItemAnimator(new DefaultItemAnimator());
            使用RecyclerView,基本上要上面四步。相比ListView只需设置Adapter而言,RecyclerView的使用看起来似乎要复杂一些。但是它的可定制性更高了,你可以自己定制自己的分割线样式或者是item的的动画。
            下面我们看下如何使用RecyclerView简单实现ListView的效果。
    activity:
      1 package com.bbk.lling.recyclerview;
      2 
      3 import android.support.v7.app.ActionBarActivity;
      4 import android.os.Bundle;
      5 import android.support.v7.widget.DefaultItemAnimator;
      6 import android.support.v7.widget.LinearLayoutManager;
      7 import android.support.v7.widget.RecyclerView;
      8 import android.view.Menu;
      9 import android.view.MenuItem;
     10 import android.view.View;
     11 import android.widget.Toast;
     12 
     13 import java.util.ArrayList;
     14 import java.util.List;
     15 
     16 /**
     17  * @Class: ListLayoutActivity
     18  * @Description: RecycleView实现listview的功能
     19  * @author: lling(www.liuling123.com)
     20  * @Date: 2015/10/29
     21  */
     22 public class ListLayoutActivity extends ActionBarActivity {
     23 
     24     private RecyclerView mRecyclerView;
     25     private ListAdapter mListAdapter;
     26     private List<String> mDatas;
     27 
     28     @Override
     29     protected void onCreate(Bundle savedInstanceState) {
     30         super.onCreate(savedInstanceState);
     31         setContentView(R.layout.activity_list_layout);
     32         initData();
     33         mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
     34         mListAdapter = new ListAdapter(this, mDatas);
     35         mListAdapter.setOnItemClickListener(new ListAdapter.OnItemClickListener() {
     36             @Override
     37             public void onItemClick(View view, int position) {
     38                 Toast.makeText(ListLayoutActivity.this, "Click" + mDatas.get(position), Toast.LENGTH_SHORT).show();
     39             }
     40 
     41             @Override
     42             public void onItemLongClick(View view, int position) {
     43                 mListAdapter.remove(position); //remove the item
     44                 Toast.makeText(ListLayoutActivity.this, "LongClick" + mDatas.get(position), Toast.LENGTH_SHORT).show();
     45             }
     46         });
     47         mRecyclerView.setAdapter(mListAdapter);
     48         /**
     49          * 设置布局管理器,listview风格则设置为LinearLayoutManager
     50          * gridview风格则设置为GridLayoutManager
     51          * pu瀑布流风格的设置为StaggeredGridLayoutManager
     52          */
     53         mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
     54         // 设置item分
     55         mRecyclerView.addItemDecoration(new ListItemDecoration(this, LinearLayoutManager.VERTICAL));
     56         // 设置item动画
     57         mRecyclerView.setItemAnimator(new DefaultItemAnimator());
     58 
     59     }
     60 
     61     @Override
     62     public boolean onCreateOptionsMenu(Menu menu) {
     63         getMenuInflater().inflate(R.menu.menu_list_layout, menu);
     64         return true;
     65     }
     66 
     67     @Override
     68     public boolean onOptionsItemSelected(MenuItem item) {
     69         switch (item.getItemId()) {
     70             case R.id.add_first:
     71                 mListAdapter.add(0, "add first");
     72                 break;
     73             case R.id.add_last:
     74                 mListAdapter.add(mListAdapter.getItemCount(), "add last");
     75                 break;
     76             case R.id.remove_first:
     77                 String value = mListAdapter.remove(0);
     78                 Toast.makeText(ListLayoutActivity.this, "remove:" + value, Toast.LENGTH_SHORT).show();
     79                 break;
     80             case R.id.remove_last:
     81                 String value1 =  mListAdapter.remove(mListAdapter.getItemCount()-1);
     82                 Toast.makeText(ListLayoutActivity.this, "remove:" + value1, Toast.LENGTH_SHORT).show();
     83                 break;
     84             case R.id.horizontal:
     85                 mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
     86                 mRecyclerView.addItemDecoration(new ListItemDecoration(this, LinearLayoutManager.HORIZONTAL));
     87                 break;
     88             case R.id.vertical:
     89                 mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
     90                 mRecyclerView.addItemDecoration(new ListItemDecoration(this, LinearLayoutManager.VERTICAL));
     91                 break;
     92         }
     93         return super.onOptionsItemSelected(item);
     94     }
     95 
     96      /* ==========This Part is not necessary========= */
     97 
     98     /**
     99      * Create datas
    100      */
    101     protected void initData() {
    102         mDatas = new ArrayList<String>();
    103         for (int i = 0; i < 100; i++) {
    104             mDatas.add(String.valueOf(i));
    105         }
    106     }
    107 
    108     /* ==========This Part is not necessary========= */
    109 }
     
    activity布局:
     1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent" >
     5 
     6     <android.support.v7.widget.RecyclerView
     7         android:id="@+id/recyclerview"
     8         android:layout_width="match_parent"
     9         android:layout_height="match_parent" />
    10 
    11 </RelativeLayout>
    Adapter:
      1 package com.bbk.lling.recyclerview;
      2 
      3 import android.annotation.SuppressLint;
      4 import android.content.Context;
      5 import android.support.v7.widget.RecyclerView;
      6 import android.util.Log;
      7 import android.view.LayoutInflater;
      8 import android.view.View;
      9 import android.view.ViewGroup;
     10 import android.widget.TextView;
     11 
     12 import java.util.List;
     13 
     14 /**
     15  * @Class: ListAdapter
     16  * @Description: 数据适配器
     17  * @author: lling(www.liuling123.com)
     18  * @Date: 2015/10/29
     19  */
     20 public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ItemViewHolder> {
     21 
     22     private List<String> mDatas;
     23     private LayoutInflater mInflater;
     24     private OnItemClickListener mOnItemClickListener;
     25 
     26     public ListAdapter(Context context, List<String> mDatas) {
     27         this.mDatas = mDatas;
     28         mInflater = LayoutInflater.from(context);
     29     }
     30 
     31     @Override
     32     public int getItemCount() {
     33         return mDatas.size();
     34     }
     35 
     36     @SuppressLint("NewApi")
     37     @Override
     38     public void onBindViewHolder(final ItemViewHolder itemViewHolder, final int i) {
     39         itemViewHolder.mTextView.setText(mDatas.get(i));
     40         if(mOnItemClickListener != null) {
     41             /**
     42              * 这里加了判断,itemViewHolder.itemView.hasOnClickListeners()
     43              * 目的是减少对象的创建,如果已经为view设置了click监听事件,就不用重复设置了
     44              * 不然每次调用onBindViewHolder方法,都会创建两个监听事件对象,增加了内存的开销
     45              */
     46             if(!itemViewHolder.itemView.hasOnClickListeners()) {
     47                 Log.e("ListAdapter", "setOnClickListener");
     48                 itemViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
     49                     @Override
     50                     public void onClick(View v) {
     51                         int pos = itemViewHolder.getPosition();
     52                         mOnItemClickListener.onItemClick(v, pos);
     53                     }
     54                 });
     55                 itemViewHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
     56                     @Override
     57                     public boolean onLongClick(View v) {
     58                         int pos = itemViewHolder.getPosition();
     59                         mOnItemClickListener.onItemLongClick(v, pos);
     60                         return true;
     61                     }
     62                 });
     63             }
     64         }
     65     }
     66 
     67     @Override
     68     public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
     69         /**
     70          * 使用RecyclerView,ViewHolder是可以复用的。这根使用ListView的VIewHolder复用是一样的
     71          * ViewHolder创建的个数好像是可见item的个数+3
     72          */
     73         Log.e("ListAdapter", "onCreateViewHolder");
     74         ItemViewHolder holder = new ItemViewHolder(mInflater.inflate(
     75                 R.layout.item_layout, viewGroup, false));
     76         return holder;
     77     }
     78 
     79     /**
     80      * 向指定位置添加元素
     81      * @param position
     82      * @param value
     83      */
     84     public void add(int position, String value) {
     85         if(position > mDatas.size()) {
     86             position = mDatas.size();
     87         }
     88         if(position < 0) {
     89             position = 0;
     90         }
     91         mDatas.add(position, value);
     92         /**
     93          * 使用notifyItemInserted/notifyItemRemoved会有动画效果
     94          * 而使用notifyDataSetChanged()则没有
     95          */
     96         notifyItemInserted(position);
     97     }
     98 
     99     /**
    100      * 移除指定位置元素
    101      * @param position
    102      * @return
    103      */
    104     public String remove(int position) {
    105         if(position > mDatas.size()-1) {
    106             return null;
    107         }
    108         String value = mDatas.remove(position);
    109         notifyItemRemoved(position);
    110         return value;
    111     }
    112 
    113 
    114     public void setOnItemClickListener(OnItemClickListener mOnItemClickListener) {
    115         this.mOnItemClickListener = mOnItemClickListener;
    116     }
    117 
    118     /**
    119      * 处理item的点击事件和长按事件
    120      */
    121     interface OnItemClickListener {
    122         public void onItemClick(View view, int position);
    123         public void onItemLongClick(View view, int position);
    124     }
    125 
    126     class ItemViewHolder extends RecyclerView.ViewHolder {
    127 
    128         private TextView mTextView;
    129 
    130         public ItemViewHolder(View itemView) {
    131             super(itemView);
    132             mTextView = (TextView) itemView.findViewById(R.id.textview);
    133         }
    134     }
    135 
    136 }
            这里值得注意的是,RecyclerView并没有提供setOnItemClickListener方法来设置item的点击事件,所以这里我们自己来实现item的点击事件,这点很坑爹有木有?没有就自己设置呗!上面代码121-124定义了一个点击接口。然后给Adapter设置定义的接口对象,然后在onBindViewHolder中为每个holder设置点击事件就行了。但是有一点得注意,因为只要滑动RecyclerView,onBindViewHolder就会不停的调用,如果不加判断的话,则会不停的创建新的点击事件对象,浪费内存,所以在设置点击事件之前需要判断一下是否已经设置过了(如上面代码46行),如果设置过了就不需要创建了。
     
    item的布局:
     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     <TextView
     6         android:id="@+id/textview"
     7         android:layout_width="wrap_content"
     8         android:layout_height="48dp"
     9         android:minWidth="48dp"
    10         android:gravity="center"
    11         android:layout_centerInParent="true"
    12         android:text="XXX"/>
    13 </RelativeLayout>
    item分割线:
     1 package com.bbk.lling.recyclerview;
     2 
     3 import android.content.Context;
     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 /**
    12  * @Class: ListItemDecoration
    13  * @Description: listview的item分割线
    14  * @author: lling(www.liuling123.com)
    15  * @Date: 2015/10/29
    16  */
    17 public class ListItemDecoration extends RecyclerView.ItemDecoration {
    18 
    19     private Drawable mDrawable;
    20 
    21     private final static int DEFAULT_ORENTATION = LinearLayoutManager.VERTICAL;
    22 
    23     private int mOrientation;
    24 
    25     public ListItemDecoration(Context context, int orientation) {
    26         if(orientation != LinearLayoutManager.HORIZONTAL && orientation != LinearLayoutManager.VERTICAL) {
    27             this.mOrientation = DEFAULT_ORENTATION;
    28         } else {
    29             this.mOrientation = orientation;
    30         }
    31         mDrawable = context.getResources().getDrawable(R.drawable.divider);
    32     }
    33 
    34     @Override
    35     public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    36         if(mOrientation == LinearLayoutManager.HORIZONTAL) {
    37             drawHorizontal(c, parent);
    38         } else {
    39             drawVertical(c, parent);
    40         }
    41     }
    42 
    43     private void drawHorizontal(Canvas c, RecyclerView parent) {
    44         int top = parent.getPaddingTop();
    45         int bottom = parent.getHeight() - parent.getPaddingBottom();
    46 
    47         int childCount = parent.getChildCount();
    48         for (int i = 0; i < childCount; i++) {
    49             View child = parent.getChildAt(i);
    50             RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
    51                     .getLayoutParams();
    52             int left = child.getRight() + params.rightMargin;
    53             int right = left + mDrawable.getIntrinsicHeight();
    54             mDrawable.setBounds(left, top, right, bottom);
    55             mDrawable.draw(c);
    56         }
    57     }
    58 
    59     private void drawVertical(Canvas c, RecyclerView parent) {
    60         int left = parent.getPaddingLeft();
    61         int right = parent.getWidth() - parent.getPaddingRight();
    62 
    63         int childCount = parent.getChildCount();
    64         for (int i = 0; i < childCount; i++) {
    65             View child = parent.getChildAt(i);
    66             android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());
    67             RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
    68                     .getLayoutParams();
    69             int top = child.getBottom() + params.bottomMargin;
    70             int bottom = top + mDrawable.getIntrinsicHeight();
    71             mDrawable.setBounds(left, top, right, bottom);
    72             mDrawable.draw(c);
    73         }
    74     }
    75 
    76     @Override
    77     public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    78         super.getItemOffsets(outRect, view, parent, state);
    79     }
    80 }
    divider.xml:
    1 <?xml version="1.0" encoding="utf-8"?>
    2 <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
    3     <size android:height="1dp" android:width="1dp"/>
    4     <!--<solid android:color="#e0e0e0"/>-->
    5     <solid android:color="#ff0000"/>
    6 </shape>
     
    好了,ListView的效果已经实现了,看下效果图
     
     
    RecyclerView实现GridView以及瀑布流效果的代码这里就不贴出来了,demo源码里面有,需要的可以下载看看。
     
     
  • 相关阅读:
    POJ2778 DNA Sequence AC自动机上dp
    codeforces732F Tourist Reform 边双联通分量
    codeforces786B Legacy 线段树优化建图
    洛谷P3588 PUS 线段树优化建图
    codeforces1301D Time to Run 模拟
    codeforces1303B National Project 二分或直接计算
    codeforces1303C Perfect Keyboard 模拟或判断欧拉路
    codeforces1303D Fill The Bag 二进制应用+贪心
    python之路——使用python操作mysql数据库
    python之路——mysql索引原理
  • 原文地址:https://www.cnblogs.com/liuling/p/2015-11-04-01.html
Copyright © 2011-2022 走看看