RecyclerView综合解析

RecyclerView

什么是RecyclerView?

RecyclerView其实就是一个在5.0推出的控件,可以用它来代替ListView和GridView,从这一点也能看出来它的特性和ListView以及GridView类似,注意我说的是整体上类似,既然是更高的版本推出的,岂能再和再和低版本的小崽子们一个层次,所以它加入了很多新的特征,下面会讲到。

为什么叫RecyclerView?

虽然在计算机界,起名字一直都比较个性,比较不符合常理,通常情况下试图通过名字来了解一件事物的人都会走火入魔,想当年,我就想知道android为啥叫android,是不是什么缩写,但是后来确实让朕很失望,类似的还有apple(这里指手机),oracle(甲骨文)通过这些名字来了解一些事物真是相当困难,但是RecyclerView和他的功能还是有一些联系的:

  1. RecyclerView不关心Item是否显示在正确的位置,以及如何显示。
  2. RecyclerView不关心Item之间如何间隔。
  3. 不关注Item增加与删除的动画效果。
  4. 它只关注如何回收和复用View(这就是叫RecycleView的原因)。

嗯?什么都不关心,那还玩个毛线啊?

这位看官说的好,RecyclerView既然敢这么玩,当然是有手段的:

  1. 不关心Item是否显示在正确的位置,以及如何显示,此时我们用LayoutManager来解决。
  2. 不关心Item之间如何间隔,此时我们用ItemDecoration来解决。
  3. 不关心Item的增加与删除的动画效果,此时用ItemAnimator来解决。

看到了吧,真正牛逼的人是不需要什么都管的,只要有人就行。

这位看官又问啦,RecyclerView都有啥人(相关类)啊?看官且看:

  • Adapter
  • ViewHolder
  • LayoutManager
  • ItemDecoration
  • ItemAnimator

O啦,主公以及大将都悉数登场了,看官可能又要问了,这阵容能干点啥大事呢? 嗯,问的好,以下就是此阵容能干的事:

  1. Just like ListView(实现listview的效果)
  2. Just like GridView(实现GridView的效果)
  3. 实现横向的ListView效果
  4. 实现横向的GridView效果
  5. 实现瀑布流(此处可以通过名字来理解其效果)
  6. 定制Item增加和删除动画

都是字啊,是骡子是马拉出来溜溜,来图让我看看!好,看官既然这么急切,那就来一波:

实现listview的效果

实现垂直GridView的效果

实现横向的GridView效果

瀑布流:

动画效果(可以自己设置各种动画)

好,准备工作完成,开始编写:

实现Recyclerview

首先:导入android-support-v7-recyclerview.jar包,如果是android studio 直接加入依赖即可。

设置主布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   >
    <android.support.v7.widget.RecyclerView
        android:id="@+id/idrecyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Hello World!" />
</RelativeLayout>

item布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorPrimaryDark"
   >
    <TextView
        android:id="@+id/item_recyclerview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

MainActivity代码:

public class MainActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private List<String> list;
    private SimpleAdap adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        iniDatas();

        iniView();
        adapter = new SimpleAdap(this,list);
        recyclerView.setAdapter(adapter);
        //设置以listview形式显示
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);
        recyclerView.setLayoutManager(layoutManager);
    }

    private void iniView() {
        recyclerView = (RecyclerView) findViewById(R.id.idrecyclerview);
    }

    private void iniDatas() {
        list = new ArrayList<>();
        Random ran = new Random(50);
        for(int i=0;i<50;i++){
            list.add(String.valueOf(ran.nextInt())+i);
        }
    }
}
class SimpleAdap extends RecyclerView.Adapter<MyViewHolder>{

    private LayoutInflater layoutInflater;
    private List<String> mData;
    private Context context;
    public SimpleAdap(Context context, List<String> list) {
        this.context = context;
        mData = list;
        layoutInflater = LayoutInflater.from(context);
    }

    //google将对viewholder的操作分成了两步,创建和绑定,体现了google对viewholder的强制性
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = layoutInflater.inflate(R.layout.item_recyclerview,parent,false);
        MyViewHolder myViewHolder = new MyViewHolder(view);
        return myViewHolder;
    }

    //绑定数据
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        holder.text.setText(mData.get(position));
    }

    @Override
    public int getItemCount() {
        return mData.size() ;
    }
}

class MyViewHolder extends RecyclerView.ViewHolder {
 public TextView text;
    public MyViewHolder(View itemView) {
        super(itemView);
        text = (TextView) itemView.findViewById(R.id.item_recyclerview);
    }
}

此时的item之间是没有分割线的

如图:

这怎么能行呢?跟块黑板似的,listview得有分割线啊!

看官且看下面,待我添加分割线!

添加分割线

其实对于recyclerView来说,添加分割线很简单,可以交给它的小弟ItemDecoration来实现:

 //设置listview之间的分割线
        DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this,DividerItemDecoration.VERTICAL_LIST);
        recyclerView.addItemDecoration(dividerItemDecoration);//参数是抽象类itemDecoration的实现类,因为没有现成的,所以从github download一个

需要注意的是,recyclerView.addItemDecoration(dividerItemDecoration);中传入的参数系统并没有为我们提供,我在此是在github上down的一个类,链接地址

现在有了分割线,如图:

利用github上的源码自定义分割条

看官心中是否有疑问,这个白色的分割线是设置的颜色?还是图片?从哪设置的?

这就需要看刚才从github上下载的那个源码了

在源码中,有这么一句代码:

final TypedArray a = context.obtainStyledAttributes(ATTRS);

通过顺藤摸瓜,我们就可以知道,白色分割线就是从style中得到的,哼哼,知道了这些那就好办了,我们可以自定义我们的分割条了。

只需要在styles.xml中添加这样的一句代码:

<item name="android:listDivider">@drawable/ic_launcher</item>

此时我用系统提供的一张图片来作为分割线,如图所示:

什么?没有看到分割线? android图标那个就是分割线(确实有点大)

在此只是实例,在正式使用的时候,我们完全可以自定义一个drawale,然后进行设置。

实现GridView

在实现之前先说一点,当我们使用recyclerview的时候,要把它作为listview和gridview的综合体,不要总想着以前的listview和gridview是两个不同的控件,这是一个思想上的转变(思想是最重要的)。

竖直gridview

//第二个参数为gridview的列数
recyclerView.setLayoutManager(new GridLayoutManager(this,4));

横向gridview

recyclerView.setLayoutManager(new StaggeredGridLayoutManager(5,StaggeredGridLayoutManager.HORIZONTAL));

注意:在使用水平的gridview的是有,itemview的宽不能为match_parent,并且上面分割线的设置在此也不适用了。

瀑布流

瀑布流,其实就是item的宽或者高不一样,造成参差不齐的效果而已!

设置瀑布管理器:

        recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));

在适配器中初始化一个数据集合:

mHeight = new ArrayList<>();
        for(int i=0;i<mData.size();i++){
            mHeight.add((int) (100+Math.random()*300));
        }

在onBindViewHolder中设置item高度:

public void onBindViewHolder(seViewHolder holder, int position) {
        holder.text.setText(mData.get(position));
        ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
        layoutParams.height = mHeight.get(position);
        holder.itemView.setLayoutParams(layoutParams);
    }

增加删除动画

设置动画:

recyclerView.setItemAnimator(new DefaultItemAnimator());

在适配器中添加两个方法:

public void add(int position){
        mData.add(position,"Insert data");
        notifyItemInserted(position);//此处要注意,和listview不一样
    }

    public void delete(int position){
        mData.remove(position);
        notifyItemRemoved(position);
    }

在onOptionsItemSelected中调用方法:

public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()){
            case R.id.listview:
                recyclerView.setLayoutManager(new LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false));
                break;
            case R.id.heng_listview:
                break;
            case R.id.gridview:
                recyclerView.setLayoutManager(new GridLayoutManager(this,4));
                //recyclerView.addItemDecoration(dividerItemDecoration);
                break;
            case R.id.heng_grid:
                recyclerView.setLayoutManager(new StaggeredGridLayoutManager(5, StaggeredGridLayoutManager.HORIZONTAL));
                break;
            case R.id.pubu:
                Intent intent = new Intent(this,PubuActivity.class);
                startActivity(intent);
                break;
            case R.id.delete:
                adapter.delete(1);
                break;
            case R.id.add:
                adapter.add(1);
                break;
        }
        return super.onOptionsItemSelected(item);
    }

添加监听

说到recyclerview的监听,我要告诉看官一个悲伤的故事—-recyclerview的监听需要自己实现

实现监听的方式有很多,在此,利用在适配器中设置接口回调的方法!

在适配器中定义接口:

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;
    }

在中定义监听:

public void onBindViewHolder(MyViewHolder holder, final int position) {
        holder.text.setText(mData.get(position));
//        ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();
//        layoutParams.height = mHeight.get(position);
//        holder.itemView.setLayoutParams(layoutParams);
        if(onItemClickListener!=null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onItemClickListener.onItemClick(v, position);
                }
            });
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    onItemClickListener.onItemLongClick(v, position);
                    return false;
                }
            });
        }
    }

使用回调方法设置监听:

adapter.setOnItemClickListener(new SimpleAdap.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toast.makeText(MainActivity.this, "item"+position, Toast.LENGTH_SHORT).show();
            }

            @Override
            public void onItemLongClick(View view, int position) {
                Toast.makeText(MainActivity.this, "long"+position, Toast.LENGTH_SHORT).show();
            }
        });

注意:如果我们此时利用上面介绍的添加删除item的方法,添加了或者删除了item,这是我们点击item的时候,会发现position会不正常,具体表现在当我们添加多个item的时候,会发现所添加的每个item点击的时候都是同一个position。

解决方法:

public void onBindViewHolder(final MyViewHolder holder, final int position) {
        holder.text.setText(mData.get(position));
        if(onItemClickListener!=null) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int layoutPosition = holder.getLayoutPosition();//用此方法得到全局position,传入点击事件中
                    onItemClickListener.onItemClick(v, layoutPosition);
                }
            });
            holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    int layoutPosition = holder.getLayoutPosition();
                    onItemClickListener.onItemLongClick(v, layoutPosition);
                    return false;
                }
            });
        }
    }

OK,散会!

相关知识点,是本人对慕课网相关课程的总结,也是作为自己的学习记录

时间: 2024-10-24 02:40:52

RecyclerView综合解析的相关文章

【FastDev4Android框架开发】RecyclerView完全解析之下拉刷新与上拉加载SwipeRefreshLayout(三十一)

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49992269 本文出自:[江清清的博客] (一).前言: [好消息]个人网站已经上线运行,后面博客以及技术干货等精彩文章会同步更新,请大家关注收藏:http://www.lcode.org 话说RecyclerView已经面市很久,也在很多应用中得到广泛的使用,在整个开发者圈子里面也拥有很不错的口碑,那说明RecyclerView拥有比ListView,GridVi

RecyclerView完全解析

RecyclerView完全解析 (一) 前言 话说RecyclerView已经面市很久,也在很多应用中得到广泛的使用,在整个开发者圈子里面也拥有很不错的口碑,那说明RecyclerView拥有比ListView,GridView之类控件有很多的优点,例如:数据绑定,Item View创建,View的回收以及重用等机制.那么今天开始我们来重点学习一下RecyclerView控件,本系列文章会包括到以下三个部分: RecyclerView控件的基本使用,包括基础,进阶,高级部分,动画之类 Recy

【FastDev4Android框架开发】RecyclerView完全解析之结合AA(Android Annotations)注入框架实例(三十)

(一).前言: 话说RecyclerView已经面市很久,也在很多应用中得到广泛的使用,在整个开发者圈子里面也拥有很不错的口碑,那说明RecyclerView拥有比ListView,GridView之类控件有很多的优点,例如:数据绑定,Item View创建,View的回收以及重用等机制.本系列文章会包括到以下三个部分: RecyclerView控件的基本使用,包括基础,进阶,高级部分,动画之类(点击进入) RecyclerView控件的实战实例(点击进入) RecyclerView控件集合AA

Android 5.X新特性之RecyclerView基本解析及无限复用

说到RecyclerView,相信大家都不陌生,它是我们经典级ListView的升级版,升级后的RecyclerView展现了极大的灵活性.同时内部直接封装了ViewHolder,不用我们自己定义ViewHolder就能实现item的回收和复用功能.当然它肯定不止这些好处,比如我们可以自定义分割线,可以更加方便的实现列表的布局方式等等.虽说我们自己在第一次使用时,会比使用listView和gridView稍微的复杂一些,需要自定义的也多了一点,但是它却更好的体现了灵活性,可以随自己的喜好来随便的

【FastDev4Android框架开发】RecyclerView完全解析,让你从此爱上它(二十八)

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49927631 本文出自:[江清清的博客] (一).前言: 话说RecyclerView已经面市很久,也在很多应用中得到广泛的使用,在整个开发者圈子里面也拥有很不错的口碑,那说明RecyclerView拥有比ListView,GridView之类控件有很多的优点,例如:数据绑定,Item View创建,View的回收以及重用等机制.那么今天开始我们来重点学习一下Rec

Android开发:ListView、AdapterView、RecyclerView全面解析

目录 AdapterView简介 AdapterView本身是一个抽象类,AdapterView及其子类的继承关系如下图: 特征: AdapterView继承自ViewGroup,本质是个容器 AdapterView可以包含多个"列表项",并将这多个列表项以合适的形式展示 AdapterView显示的列表项内容由Adapter提供 它派生的子类在用法上也基本相似,只是在显示上有一定区别,因此把他们也归为一类. 由AdapterView直接派生的三个类: AbsListView.AbsS

Android RecyclerView 使用解析

RecyclerView出现已经有一段时间了,相信大家肯定不陌生了,大家可以通过导入support-v7对其进行使用. 据官方的介绍,该控件用于在有限的窗口中展示大量数据集,其实这样功能的控件我们并不陌生,例如:ListView.GridView. 那么有了ListView.GridView为什么还需要RecyclerView这样的控件呢?整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecorati

【FastDev4Android框架开发】RecyclerView完全解析之打造新版类Gallery效果(二十九)

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/49946589 本文出自:[江清清的博客] (一).前言: 话说RecyclerView已经面市很久,也在很多应用中得到广泛的使用,在整个开发者圈子里面也拥有很不错的口碑,那说明RecyclerView拥有比ListView,GridView之类控件有很多的优点,例如:数据绑定,Item View创建,View的回收以及重用等机制.本系列文章会包括到以下三个部分: R

【FastDev4Android框架开发】实例解析之SwipeRefreshLayout+RecyclerView+CardView(三十五)

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50087873 本文出自:[江清清的博客] (一).前言: 作为Android L开始,Google更新了新控件RecyclerView和CardView,这两个控件在之前的文章中已经做了详细介绍和使用,同时在前面还对下拉刷新组件SwipeRefreshLayout进行相关讲解.本来该专题不在更新了,正好昨天有一个群友问到了怎么样结合SwipeRefreshLayou