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源码里面有,需要的可以下载看看。
     
     
  • 相关阅读:
    Web安全测试之XSS(转)
    轻松学习RSA加密算法原理 (转)
    firewall 允许app访问网络
    点击了一个link button,查看后台调用
    kentico中提示Message: An invalid SQL query was used.
    iis browse的时候,直接通过本地的局域网ip打开页面
    asp.net web site中reference的version的autoupdate
    Adding Kentico controls to the Visual Studio toolbox
    sql server 数据库展开变慢
    kentico中的page template的使用
  • 原文地址:https://www.cnblogs.com/liuling/p/2015-11-04-01.html
Copyright © 2011-2022 走看看