zoukankan      html  css  js  c++  java
  • 浅谈RecyclerView(完美替代ListView,GridView)

    Android RecyclerView 是Android5.0推出来的,导入support-v7包即可使用。

    个人体验来说,RecyclerView绝对是一款功能强大的控件。

    首先总结下RecyclerView的特点:

    1.支持不同方向,不同排版模式,实现多种展现数据的形式,涵盖了ListView,GridView,瀑布流等数据表现的形式

    2.内部实现了回收机制,无需我们考虑View的复用情况

    3.取消了onItemClick等点击事件,需要自己手动去写

    ------------------------------------------------------------------------------------

    那么让我们通过一些Demo来了解RecyclerView的基本使用

     android studio 

    build.gradle文件中 dependencies中添加 

    compile 'com.android.support:recyclerview-v7:22.+'

    首先,要导入support-v7 包

    import android.support.v7.widget.RecyclerView;

    RecyclerView和ListView的使用一样,都需要有对应的Adapter,列表项布局,数据源

    1.先写主Activity布局

    可以看到RecyclerView的标签

    <android.support.v7.widget.RecyclerView>
     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2               xmlns:tools="http://schemas.android.com/tools" xmlns:app="http://schemas.android.com/apk/res-auto"
     3               android:layout_width="match_parent"
     4               android:layout_height="match_parent"
     5               android:orientation="vertical"
     6               tools:context="com.xqx.superapp.app.Android5Activity">
     7 
     8     <Button
     9             android:text="添加一个数据"
    10             android:layout_width="wrap_content"
    11             android:layout_height="wrap_content"
    12             android:onClick="btnAddItem"
    13             />
    14     <Button
    15             android:text="删除第一个"
    16             android:onClick="btnRemoveItem"
    17             android:layout_width="wrap_content"
    18             android:layout_height="wrap_content"/>
    19     
    20     <android.support.v7.widget.RecyclerView
    21         android:id="@+id/recycle_view"
    22         android:layout_width="match_parent"
    23         android:layout_height="match_parent"
    24         >
    25     </android.support.v7.widget.RecyclerView>
    26 
    27 </LinearLayout>

    菜单项布局,标准的上面图片,下面文字

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:gravity="center"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent">
            <ImageView
                    android:id="@+id/item_icon"
                    android:src="@mipmap/machao_moqi"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"/>
            <TextView
                    android:id="@+id/item_title"
                    android:text="名称"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    />
    </LinearLayout>

    2.接下来就看Activity代码了

    首先看成员变量,与ListView,GridView一样 标准三样, 控件,数据源,适配器

    private List<String> data;          
    private RecyclerView recyclerView;
    private MyRecycleAdapter adapter;   //自定义适配器,继承RecyclerView.Adapter

    接着我们必须要自定义一个ViewHolder,这个ViewHolder 必须要继承 RecyclerView.ViewHolder

    注意RecyclerView不再提供onItemClick事件监听,所以需要我们自己手工写监听事件的方法

    private static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
            public ImageView imageView;
            public TextView textView;
    
            public ViewHolder(View itemView) {
                super(itemView);
                // 通常ViewHolder的构造,就是用于获取控件视图的
                imageView = (ImageView) itemView.findViewById(R.id.item_icon);
                textView = (TextView) itemView.findViewById(R.id.item_title);
                // TODO 后续处理点击事件的操作
                itemView.setOnClickListener(this);
    
            }
            @Override
            public void onClick(View v) {
                int position = getAdapterPosition();
                Context context = imageView.getContext();
                Toast.makeText(context,"显示第"+position+"个项",Toast.LENGTH_SHORT).show();
            }
        }

    再让我们看自定义适配器,注意这里的参数是ViewHolder,这个ViewHodler是我们自己的,不要导入v7包下的ViewHolder,

    之后要重写三个方法

    private class MyRecycleAdapter extends RecyclerView.Adapter<ViewHolder>{
      
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    return null;
    }

    @Override
    public void onBindViewHolder(ViewHolder viewHolder, int i) {

    }

    @Override
    public int getItemCount() {
    return 0;
    }

    }

    在自定义适配器MyRecycleAdapter中,首先要写一个构造方法,因为有数据源,所有构造方法里必然有List

    private List<String> strings;
    public MyRecycleAdapter(List<String> strings) {
         this.strings = strings;
    }

    然后就要重写三个方法了,

     1 @Override
     2 public int getItemCount() {
     3     int ret = 0;
     4     if (strings != null) {
     5         ret = strings.size();
     6      }
     7         return ret;
     8 }
     9 
    10  @Override
    11         public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    12             ViewHolder ret = null;
    13             // 不需要检查是否复用,因为只要进入此方法,必然没有复用
    14             // 因为RecyclerView 通过Holder检查复用
    15             View v = LayoutInflater.from(Android5Activity.this).inflate(R.layout.item_recycler, viewGroup, false);
    16             ret = new ViewHolder(v);
    17             return ret;
    18         }
    19 
    20 @Override
    21         public void onBindViewHolder(ViewHolder viewHolder, int i) {
    22             // 1.这里进行图片的加载
    23             viewHolder.textView.setText(strings.get(i));
    24             int resId = R.mipmap.ic_launcher;
    25             int index = i%5;
    26             switch (index){
    27                 case 0:
    28                     resId = R.mipmap.a11;
    29                     break;
    30                 case 1:
    31                     resId = R.mipmap.a33;
    32                     break;
    33                 case 2:
    34                     resId = R.mipmap.a22;
    35                     break;
    36             }
    37             viewHolder.imageView.setImageResource(resId);
    38         }
    View Code

    ---------------------------------------------------------------------------------------------------------------

    完成自定义适配器和自定义ViewHolder的代码 就要进行RecyclerView的使用了

    首先 要了解  RecyclerView.LayoutManager 这个属性

    用于进行一个布局的设置,可以设置显示模式,ListView或者GridView或者瀑布流

    1.ListView显示模式

    1 // 1.线性布局
    2         LinearLayoutManager layoutManager =
    3                 new LinearLayoutManager(this,   // 上下文
    4                                         LinearLayout.VERTICAL,  //垂直布局,
    5                                         false);

                                        

    2.GridView显示模式

    1 // 2.Grid布局
    2         RecyclerView.LayoutManager layoutManager =
    3                 new GridLayoutManager(this,
    4                                       2,  // 每行显示item项数目
    5                                       GridLayoutManager.HORIZONTAL, //水平排列
    6                                       false
    7                                       );

                                        

    3.瀑布流显示模式

    1 // 3.瀑布流
    2         RecyclerView.LayoutManager layoutManager =
    3                 new StaggeredGridLayoutManager(3,  // 每行显示的item项数目
    4                         StaggeredGridLayoutManager.VERTICAL);  // 垂直排列

    以上三种显示模式任意设置一种 就可以继续下面的代码

    recyclerView.setLayoutManager(layoutManager);
            // 设置 RecyclerView的Adapter
            // 注意一定在设置了布局管理器之后调用
            adapter = new MyRecycleAdapter(data);
            recyclerView.setAdapter(adapter);

    最后记得加上“添加一个数据”,“删除第一个数据”的按钮响应事件。

    首先看一下以往我们对listview,gridview等等的删除某一项的操作

    先在数据源中删除该位置的数据,然后刷新整个适配器,那么就可能会造成列表闪屏的问题,还有为了删除添加一个数据项而操作整个数据源的问题

    public void btnAddItem(View view) {
            data.add(0,"Time:"+System.currentTimeMillis());
            adapter.notifyDataSetChanged();
        }
        public void btnRemoveItem(View view) {
            if (!data.isEmpty()) {
                data.remove(0);
            }
            adapter.notifyItemRemoved(0);
        }

     而RecyclerView为我们提供了一些新的实用的方法:

    public void add(ViewModel item, int position) {
        items.add(position, item);    //数据源先添加该数据
        notifyItemInserted(position); //在某个位置刷新即可
    }
     
    public void remove(ViewModel item) {
        int position = items.indexOf(item);
        items.remove(position);      //数据源先删除该数据
        notifyItemRemoved(position); //在某个位置删除即可
    }

    完整代码:

      1 package com.xqx.superapp.app;
      2 
      3 import android.app.Activity;
      4 import android.content.Context;
      5 import android.support.v7.app.ActionBarActivity;
      6 import android.os.Bundle;
      7 import android.support.v7.widget.GridLayoutManager;
      8 import android.support.v7.widget.LinearLayoutManager;
      9 import android.support.v7.widget.RecyclerView;
     10 import android.support.v7.widget.StaggeredGridLayoutManager;
     11 import android.util.Log;
     12 import android.view.*;
     13 import android.widget.*;
     14 
     15 import java.util.LinkedList;
     16 import java.util.List;
     17 
     18 
     19 public class Android5Activity extends Activity {
     20 
     21     private List<String> data;
     22     private RecyclerView recyclerView;
     23     private MyRecycleAdapter adapter;
     24 
     25     @Override
     26     protected void onCreate(Bundle savedInstanceState) {
     27         super.onCreate(savedInstanceState);
     28         setContentView(R.layout.activity_android5);
     29         data = new LinkedList<String>();
     30         recyclerView = (RecyclerView) findViewById(R.id.recycle_view);
     31         // 设置布局管理器
     32         // 支持 单列线性排列,支持GridView模式,瀑布流模式
     33         // 1.线性布局
     34         LinearLayoutManager layoutManager =
     35                 new LinearLayoutManager(this,   // 上下文
     36                                         LinearLayout.VERTICAL,  //垂直布局,
     37                                         false);
     38 
     39 //        // 2.Grid布局
     40 //        RecyclerView.LayoutManager layoutManager =
     41 //                new GridLayoutManager(this,
     42 //                                      2,
     43 //                                      GridLayoutManager.HORIZONTAL,
     44 //                                      false
     45 //                                      );
     46 //
     47 //         // 3.瀑布流
     48 //        RecyclerView.LayoutManager layoutManager =
     49 //                new StaggeredGridLayoutManager(3,
     50 //                        StaggeredGridLayoutManager.VERTICAL);
     51         recyclerView.setLayoutManager(layoutManager);
     52         // 设置 RecyclerView的Adapter
     53         // 注意一定在设置了布局管理器之后调用
     54         adapter = new MyRecycleAdapter(data);
     55         recyclerView.setAdapter(adapter);
     56     }
     57 
     58     public void btnAddItem(View view) {
     59         data.add(0,"Time:"+System.currentTimeMillis());
     60         adapter.notifyDataSetChanged();
     61     }
     62 
     63     public void btnRemoveItem(View view) {
     64         if (!data.isEmpty()) {
     65             data.remove(0);
     66         }
     67         adapter.notifyItemRemoved(0);
     68     }
     69 
     70     /**
     71      * 继承RecyclerView.Adapter,用于显示数据
     72      * 需要定义并且使用 ViewHolder ,必须要使用
     73      */
     74     private class MyRecycleAdapter extends RecyclerView.Adapter<ViewHolder>{
     75         private List<String> strings;
     76         public MyRecycleAdapter(List<String> strings) {
     77             this.strings = strings;
     78         }
     79 
     80         @Override
     81         public int getItemCount() {
     82             int ret = 0;
     83             if (strings != null) {
     84                 ret = strings.size();
     85             }
     86             return ret;
     87         }
     88 
     89         @Override
     90         public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
     91             ViewHolder ret = null;
     92             // 不需要检查是否复用,因为只要进入此方法,必然没有复用
     93             // 因为RecyclerView 通过Holder检查复用
     94             View v = LayoutInflater.from(Android5Activity.this).inflate(R.layout.item_recycler, viewGroup, false);
     95             ret = new ViewHolder(v);
     96             return ret;
     97         }
     98 
     99         @Override
    100         public void onBindViewHolder(ViewHolder viewHolder, int i) {
    101             viewHolder.textView.setText(strings.get(i));
    102             int resId = R.mipmap.ic_launcher;
    103             int index = i%5;
    104             switch (index){
    105                 case 0:
    106                     resId = R.mipmap.a11;
    107                     break;
    108                 case 1:
    109                     resId = R.mipmap.a33;
    110                     break;
    111                 case 2:
    112                     resId = R.mipmap.a22;
    113                     break;
    114             }
    115             viewHolder.imageView.setImageResource(resId);
    116         }
    117     }
    118 
    119     /**
    120      * 创建自己的ViewHolder ,必须要继承RecyclerView.ViewHolder
    121      */
    122     private static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
    123         public ImageView imageView;
    124         public TextView textView;
    125 
    126         public ViewHolder(View itemView) {
    127             super(itemView);
    128             // 通常ViewHolder的构造,就是用于获取控件视图的
    129             imageView = (ImageView) itemView.findViewById(R.id.item_icon);
    130             textView = (TextView) itemView.findViewById(R.id.item_title);
    131             // TODO 后续处理点击事件的操作
    132             itemView.setOnClickListener(this);
    133 
    134         }
    135         @Override
    136         public void onClick(View v) {
    137             int position = getAdapterPosition();
    138             Context context = imageView.getContext();
    139             Toast.makeText(context,"显示第"+position+"个项",Toast.LENGTH_SHORT).show();
    140         }
    141     }
    142 }
    View Code

    -------------------------------------------------------------------------------------------------------------

    其他相关:

    浅谈FloatingActionButton(悬浮按钮)

    浅谈DrawerLayout(抽屉效果)

    浅谈TabLayout(ViewPager+Tab联动)

    浅谈GridLayout(网格布局)

  • 相关阅读:
    fastDFS与nginx整合2
    fastDFS分布式文件系统
    NIO编程
    Nginx正向代理与反向代理
    JAVA序列化
    FileUpload问题
    测试覆盖率实现技术
    Hutool 功能特色:
    自建右键服务器
    20191123-SWITCH后面跟的参数不能为string类型
  • 原文地址:https://www.cnblogs.com/xqxacm/p/4926199.html
Copyright © 2011-2022 走看看