MaterialDesign-RecyleView探究及使用【一】-基本用法

概述

RecylerView控件从Android 5.0开始谷歌公司推出的新控件用于替代ListView、GridView的控件。不是已经有ListView了吗,为什么还要RecyclerView呢?下面我们看下recyleview都有哪些特点。

recyleview主要特点:

1、RecyclerView提供了一种插拔式的体验,高度的解耦,异常的灵活;

2、自带了性能优化(ViewHolder复用机制);

3、低耦合高内聚。(通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现不同视图效果。)

recyleview缺点:(同listveiw对比)

1、RecyclerView没有条目点击、长按事件,需要自己封装。

2、RecyclerView没有默认的分割线,需要自己绘制。

3、RecyclerView 没有添加头部和底部视图的功能

recyleview主要功能:

我们会从如下几个功能方面实现recyleview主要功能

1、通过布局管理器LayoutManager控制你想要其显示视图样式的方式;

2、通过ItemDecoration控制Item间的间隔线的展示(需要自定义绘制);

3、通过ItemAnimator控制Item增删的动画

4、通过自己封装RecyclerView条目点击、长按事件;

5、RecyclerView 添加头部和底部(需要自己实现,recyleview自身没有此功能)

6、RecyclerView 功能延展

基本用法

RecyclerView 使用时的基本代码块:

相对于ListView的代码,ListView可能只需要去设置一个adapter就能正常使用了。而RecyclerView基本需要下面好多的步骤,那么为什么会添加这么多的步骤呢?其高度的解耦,给予你充分的定制自由(所以你才可以轻松的通过这个控件实现ListView,GirdView,瀑布流等效果)。

recyleview = this.findViewById(R.id.recyleview);

//设置布局管理器

recyleview.setLayoutManager(linearLayoutManager);

//添加分割线

recyleview.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.HORIZONTAL, R.drawable.line_diver_gray));

// //设置Item增加、移除动画

recyleview.setItemAnimator(new DefaultItemAnimator());

//设置adapter

adapter = new RVElementaryAdapter(data);

recyleview.setAdapter(adapter);

//设置条目的点击事件

adapter.setOnItemClickListener(this);

//设置条目的长按事件

adapter.setOnItemLongClickListener(this);

RecyclerView的Adapter的写法:

在了解了RecyclerView的一些控制之后,紧接着来看看它的Adapter的写法,RecyclerView的Adapter与ListView的Adapter还是有点区别的,RecyclerView.Adapter,需要实现3个方法: 

1、 onCreateViewHolder() 

这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。该方法把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。

2、 onBindViewHolder() 

这个方法主要用于适配渲染数据到View中。方法提供给你了一viewHolder而不是原来的convertView。

3、 getItemCount() 

这个方法就类似于BaseAdapter的getCount方法了,即总共有多少个条目。

如下是recyleview的adapter基本代码块:

public class RVElementaryAdapter extends RecyclerView.Adapter {

    @Override

    public ElementaryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {

        // 创建ViewHolder

        View itemView = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent,false);

        ElementaryViewHolder elementaryViewHolder = new ElementaryViewHolder(itemView);

        return elementaryViewHolder;

    }

    @Override

    public void onBindViewHolder(@NonNull RVElementaryAdapter.ElementaryViewHolder holder, int position) {

        //绑定数据

        holder.tv.setText(data.get(position));

    }

    @Override

    public int getItemCount() {

        return data == null? 0 :data.size();

    }

}

实现的列表效果图如下:


RecyclerView 控制布局样式LayoutManager:

上面实现了类似ListView样子的Demo,通过使用其默认的LinearLayoutManager。RecyclerView.LayoutManage这是一个抽象类,系统提供了如下3个实现类:

1、LinearLayoutManager 现行管理器,支持横向、纵向。

2、GridLayoutManager 网格布局管理器

3、StaggeredGridLayoutManager 瀑布就式布局管理器

下面实现以下各种视图间的转化效果:

代码主要是通过recyleview.setLayoutManager(linearLayoutManager);设置不同的layoutManager来展示不同的视图样式,如下关键的代码快:

/**

*切换布局效果

*/

private void changeView(){

    adapter.setViewType(currentViewType);

    recyleview.removeItemDecoration(dividerItemDecoration);

    recyleview.removeItemDecoration(dividerGridViewItemDecoration);

    switch (currentViewType){

        case Constnats.VIEW_TYPE_LISTVIEW:

            recyleview.addItemDecoration(dividerItemDecoration);

            recyleview.setLayoutManager(linearLayoutManager);

            break;

        case Constnats.VIEW_TYPE_GRIDVIEW:

            recyleview.addItemDecoration(dividerGridViewItemDecoration);

            recyleview.setLayoutManager(gridLayoutManager);

            break;

        case Constnats.VIEW_TYPE_HORIZONTALGRIDVEW:

            recyleview.addItemDecoration(dividerGridViewItemDecoration);

            recyleview.setLayoutManager(horizontalGridLayoutManager);

            break;

        case Constnats.VIEW_TYPE_STAGGEREDGRIDVIEW:

            recyleview.addItemDecoration(dividerGridViewItemDecoration);

            recyleview.setLayoutManager(staggeredGridLayoutManager);

            break;

    }

}

效果图如下:


RecyclerView添加条目、删除条目功能,并添加条目动画:

注意的点:

1、RecyclerView.Adapter中添加删除条目需要刷新视图,平时我们刷新的方法调用notifyDataSetChanged();

--notifyDataSetChanged();列表全局刷新,给recyleview添加增删条目的动画时,调用这种刷新方法时无法生效的

2、RecyclerView.Adapter中为我们提供了很多自带酷炫的增加删除动画,包括局部刷新的方法。

--notifyItemInserted(int position): 列表position位置添加一条数据时可以调用,伴有动画效果

--notifyItemRemoved(int position) :列表position位置移除一条数据时调用,伴有动画效果

--notifyItemMoved(int fromPosition, int toPosition) 列表fromPosition位置的数据移到toPosition位置时调用,伴有动画效果

--notifyItemRangeChanged(int positionStart, int itemCount) 列表从positionStart位置到itemCount数量的列表项进行数据刷新

--notifyItemRangeInserted(int positionStart, int itemCount) 列表从positionStart位置到itemCount数量的列表项批量添加数据时调用,伴有动画效果

·notifyItemRangeRemoved(int positionStart, int itemCount) 列表从positionStart位置到itemCount数量的列表项批量删除数据时调用,伴有动画效果

3、实际增删操作过程中position不会自动增加,导致数据错位的问题,所以,当我们需要使用这些特效方法的时候,必须要重新刷新一遍数据,纠正position。

4、设置Item增加、移除动画recyleview.setItemAnimator(new DefaultItemAnimator());

在adapter中实现添加和删除条目的功能,避免了数据错位的问题,功能代码如下:

/**

    * 添加条目

    * @param position

    */

    public void addData(int position){

        data.add(position,"additem"+position);

        heights.add(position,(int) Math.max(200,Math.random()*600));

        notifyItemInserted(position);

        // 加入如下代码保证position的位置正确性

        if (position != data.size() - 1) {

            //列表从positionStart位置到itemCount数量的列表项进行数据刷新

            notifyItemRangeChanged(position, data.size() - position);

        }

//    notifyDataSetChanged();

    }

    /**

    * 移除条目

    * @param position

    */

    public void removeData(int position){

        data.remove(position);

        heights.remove(position);

        notifyItemRemoved(position);

        // 加入如下代码保证position的位置正确性

        if (position != data.size() - 1) {

            //列表从positionStart位置到itemCount数量的列表项进行数据刷新

            notifyItemRangeChanged(position, data.size() - position);

        }

//        notifyDataSetChanged();

    }

RecyleView添加点击事件和长按事件Click and LongClick:

上面说到RecyleView的缺点系统没有提供ClickListener和LongClickListener,我们也可以自己去添加,需要多实现些代码。 可以通过adapter中自己去提供回调自己去实现。adapter.setOnItemClickListener(this)设置条目的点击事件;adapter.setOnItemLongClickListener(this)设置条目的长按事件,

注意:解决点击position可能错位的问题,通过构造点击事件把position传给自己实现的点击事件,以便于记录点击确定的position

关键代码块如下:

@Override

public void onBindViewHolder(@NonNull RVElementaryAdapter.ElementaryViewHolder holder, int position) {

    if(itemClickListener != null) {

        holder.tv.setOnClickListener(new MyClickListener(position));

    }

    if(itemLongClickListener != null) {

        holder.tv.setOnLongClickListener(new MyLongClickListener(position));

    }

}

private ItemClickListener itemClickListener;

private ItemClickListener itemLongClickListener;

/**

* 设置点击事件

*/

public void setOnItemClickListener(ItemClickListener itemClickListener){

    this.itemClickListener = itemClickListener;

}

/**

* 设置长按点击事件

*/

public void setOnItemLongClickListener(ItemClickListener itemLongClickListener){

    this.itemLongClickListener = itemLongClickListener;

}

public interface ItemClickListener{

    void onItemClick(int position);

    void onItemLongClick(int position);

}

/**

* 条目的点击事件

*/

public class MyClickListener implements View.OnClickListener{

    int position;

    MyClickListener(int position){

        this.position = position;

    }

    @Override

    public void onClick(View v) {

        itemClickListener.onItemClick(position);

    }

}

/**

* 条目的长按事件

*/

public class MyLongClickListener implements View.OnLongClickListener{

    int position;

    MyLongClickListener(int position){

        this.position = position;

    }

    @Override

    public boolean onLongClick(View v) {

        itemLongClickListener.onItemLongClick(position);

        return true;

    }

}

到此基本介绍了RecylerView常见用法,包含了:

1、系统提供了几种LayoutManager的使用;

2、如何使用ItemAnimator为RecylerView去添加Item移除、添加以及动画效果。

3、介绍了如何添加ItemClickListener与ItemLongClickListener。

4、recyleview的adapter的用法

接下来会看一下RecyleView添加分割线的功能。

源码demo链接:

https://github.com/heiyl/recyleview

csdn地址:https://blog.csdn.net/hylxnq/article/details/80265880

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容