RecyclerView之学习使用BRVAH框架

前言

RecyclerView(一)
RecyclerView加点击事件(二)
RecyclerView的滑动监听(三)
RecyclerView之横向展示(四)
RecyclerView之瀑布流(五)
RecyclerView优化

一、准备工作

这个框架是BaseRecyclerViewAdapterHelper,是Git上一个比较热门的开源项目。

1、如何导入到工程中

先在 工程的build.gradle(Project:XXXX) 的 repositories 添加:

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" } // 这句话是自己额外添加的
    }
}

在使用的mudle中添加:

    compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'

2、开启混淆

最好参照Git上使用:

-keep class com.chad.library.adapter.** {
*;
}
-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter
-keep public class * extends com.chad.library.adapter.base.BaseViewHolder
-keepclassmembers  class **$** extends com.chad.library.adapter.base.BaseViewHolder {
     (...);
}

二、基础使用

1、建立 Adapter

这里有两种建立方式,使用起来很方便

1.1、单独建立Adapter

/** 自定义一个类,让其继承BaseQuickAdapter(T,K)范型一是实体类,是你要用于RecyclerView的实体类,
K一般是固定的,但也可以是继承BaseViewHolder的类,然后别的就可以自己生成*/

public class MyRecyclerViewAdpter extends BaseQuickAdapter {
    public MyRecyclerViewAdpter (@LayoutRes int layoutResId, @Nullable List data) {
        super(layoutResId, data);
       //构造方法一,参数是layoutResId,这是你希望每个条目展示成什么样,这是那个布局的id
       //data,可以看见是list集合,所以这里是你的数据源
    }

    public MyRecyclerViewAdpter (@Nullable List data) {
        super(data);
        //这里只有一个参数,就是数据源
    }

    public MyRecyclerViewAdpter (@LayoutRes int layoutResId) {
        super(layoutResId);
        //这里只有一个参数,就是item布局id
    }
    @Override
    protected void convert(BaseViewHolder helper, myBenn item) {
        //这个方法很重要,在这里你可以完成基本的操作,
       (1)找到item上某个控件,并且给它赋值,以下面为例:
                  helper.setText(R.id.textView_my_name,item.getName());只需传入控件id和要赋予的值
                 (这里是实体类的某个值,并不用像以前,list.get(position).getName()那么麻烦)
       (2)加载图片
                 Glide.with(mContext).load(item.getUrl).into((ImageView) helper.getView(R.id._my_pic));
                  这里主要是通过helper.getView()方法,通过传入控件id得到那个控件。
       (3)给item中添加点击事件,在这里需要完成添加,这样才能用
                 helper.addOnClickListener(R.id.textView_my_name);
                 helper.addOnLongClickListener(R.id.textView_my_name);
             这里算是基础工作,想给那个控件添加点击|长点击都在这里添加
       (4)helper.getLayoutPosition();
                 此方法是得到当前条目的位置
    }
    
}

使用的时候,直接如下:

    private MyRecyclerViewAdpter  myRecyclerAdapter;
    先定义全局变量。
    myRecyclerAdapter = new MyRecyclerViewAdpter(R.layout.recycler_item, mList);
   完成构建

1.2、在使用的时候创建Adapter

    private BaseQuickAdapter baseQuickAdapter;
    使用系统的BaseQuickAdapter,不在自定义自己的Adapter。
    myBaseAdapter = new BaseQuickAdapter(R.layout.recycler_item) {
            @Override
            protected void convert(BaseViewHolder helper, myBenn item) {
                //发现也是和第一种方式一样,不过这个不用自己在定义自己的Adapter了
            }
        };

2、绑定RecyclerView

2.1建立关系

前面都有介绍,具体参照开头,这里介绍一种:
        RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
        mRecyclerView.setLayoutManager(layoutManager);
        myRecyclerAdapter = new MyRecyclerViewAdpter(R.layout.recycler_item, mList);
        mRecyclerView.setAdapter(myRecyclerAdapter); //别忘记setAdapter()

2.2关于数据源更新

(1) myRecyclerAdapter.notifyDataSetChanged();

更新整个RecyclerView,根据新的List集合中数据来更新

(2)myRecyclerAdapter.addData(mList);

 /**
     * add new data to the end of mData
     *
     * @param newData the new data collection
     */
    public void addData(@NonNull Collection newData) {
        mData.addAll(newData);
        notifyItemRangeInserted(mData.size() - newData.size() + getHeaderLayoutCount(), newData.size());
        compatibilityDataSizeChanged(newData.size());
    }

添加新的数据在原来的数据上,封装了notifyDataSetChanged,比如,界面展示数据10条,你调用了这个方法,可以使得界面上展示20条,相当于再次拼接上了。

(3)myRecyclerAdapter.setNewData(mList);

 /**
     * setting up a new instance to data;
     *
     * @param data
     */
    public void setNewData(@Nullable List data) {
        this.mData = data == null ? new ArrayList() : data;
        if (mRequestLoadMoreListener != null) {
            mNextLoadEnable = true;
            mLoadMoreEnable = true;
            mLoading = false;
            mLoadMoreView.setLoadMoreStatus(LoadMoreView.STATUS_DEFAULT);
        }
        mLastPosition = -1;
        notifyDataSetChanged();
    }

取代原来的数据。并不会和上面一样拼接上。 也是对于notifyDataSetChanged的封装。

(4)总结

如果喜欢直接用NotifyDataSetChanged方法,那么注意mList要自己手动add,才能保存原来数据。
而(2)和(3)则是对于mList进行了操作,一般就是清空或者是继续添加。

三、添加点击事件

(1)添加条目点击事件

myRecyclerAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                Log.d("xljnewstudy", "条目短时间点击事件,点击的是"+position);
            }
        });

(2) 添加条目长点击事件

myRecyclerAdapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(BaseQuickAdapter adapter, View view, int position) {
                Log.d("xljnewstudy", "条目长时间点击事件");
                return false;
            }
        });

(3)添加item上单独控件的点击事件

myRecyclerAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                Log.d("xljnewstudy", "具体View短时间点击事件");
                //注意:这里的前提是你在conver方法中添加了,如果 多个控件添加了,可以采用
                //switch(view.getId())方法来区分
            }
        });

(4)添加item上单独控件的长点击事件

 myRecyclerAdapter.setOnItemChildLongClickListener(new BaseQuickAdapter.OnItemChildLongClickListener() {
            @Override
            public boolean onItemChildLongClick(BaseQuickAdapter adapter, View view, int position) {
                Log.d("xljnewstudy", "具体View长时间点击事件");
                return false;
            }
        });

(5)使用RecyclerView添加点击事件

  mRecyclerView.addOnItemTouchListener();  此方法也是添加点击,但是会重复添加了,不建议用

(6)特殊需求

getViewByPosition(RecyclerView recyclerView, int position, @IdRes int viewId) 
如果你想在点击事件中,获得其他的子控件的话。

四、给item 展示出来设置动画

4.1 设置动画

        myRecyclerAdapter.openLoadAnimation(BaseQuickAdapter.SLIDEIN_LEFT);

        //这里采用的是给定好的动画,还有
       ALPHAIN (渐显)、SCALEIN (缩放)、SLIDEIN_BOTTOM 、SLIDEIN_LEFT 、SLIDEIN_RIGHT 、

4.2

        myRecyclerAdapter.setNotDoAnimationCount(-1);
        如果不设置这个属性,那么默认直接展示在用户面前那一屏上没有动画
        参数是自己填,填什么,表示从第几个item开始出来的动画,设置-1,默认都有动画

4.3

        myRecyclerAdapter.isFirstOnly(false);
        如果设置为true ,那么每个item只有一次执行动画机会,比如你滑出屏之后,再进来,就没有动画了

4.4 使用自己定义的动画

 myRecyclerAdapter.openLoadAnimation(new BaseAnimation() {
            @Override
            public Animator[] getAnimators(View view) {
                return new Animator[0];
                //在这里写动画的代码
            }
        });

五 、添加头布局或者尾布局或者空布局

这里以一张图片为例

5.1 添加头布局

       ImageView mImage = new ImageView(MainActivity.this);
        mImage.setBackgroundResource(R.mipmap.ic_launcher);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 500);
        mImage.setLayoutParams(params);
        myRecyclerAdapter.addHeaderView(mImage); //核心代码
//      myRecyclerAdapter.setHeaderViewAsFlow(true);//此属性说是占满一行,经过测试,暂时没有发现用处

如图所示,添加了一个头布局,如果你不设置一些属性的话,那么这个ImageView的高度只有item高度那么高
这个是默认的,

5.2 添加尾布局

        ImageView mi = new ImageView(MainActivity.this);
        mi.setBackgroundResource(R.mipmap.ic_launcher);
        myRecyclerAdapter.addFooterView(mi); //核心代码
//      myRecyclerAdapter.setFooterViewAsFlow(true);//此属性说是占满一行,经过测试,暂时没有发现用处

如图所示,如果添加了一个尾布局,但是默认只占有一个item的高度.

5.3 添加空布局

 ImageView ms = new ImageView(MainActivity.this);
 ms.setBackgroundResource(R.mipmap.ic_launcher);
 RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(250, 250);
 params.addRule(RelativeLayout.CENTER_IN_PARENT);
ms.setLayoutParams(params);
myRecyclerAdapter.setEmptyView(ms);//可以添加一个view

如上,添加了一张图片,只是添加一个View,它会默认的填充在左上角,而且很小
不会按照你设置的属性来

        myRecyclerAdapter.setEmptyView(R.layout.recyer_empty, mRecyclerView);

如上,是另一种方法,将你想要展示的界面以布局的形式添加,但是,如果不添加RecyclerView
就会报运行时错误。

5.4 一些说明

如果你只是这样设置了三个布局,那么在没有数据的时候,只会展示空白布局,但是有一些额外的需求
比如同时展示头、尾、空、之类的

 myRecyclerAdapter.setHeaderAndEmpty(true); //让头布局和空布局一起展示
myRecyclerAdapter.setHeaderFooterEmpty(true, true);//两个参数,前面是允许头和空,后面是允许尾和空

另外,你设置了头布局或者尾布局,在设置item点击事件的时候,根本不管用,你点击第一个item,依旧是
positon = 0 ;所以点击事件需要自己额外添加,就是说,把头布局和尾布局从内容区域分开了。

六、上拉刷新

6.1 一行代码搞定

 myRecyclerAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
            @Override
            public void onLoadMoreRequested() {
                Log.d("xljnewstudy", "进入了上拉加载更多");
                //自带了上拉刷新的布局,
               //在这里你要完成联网或者别的方式,获取更多的数据。
            }
        }, mRecyclerView);

这个自带加载动画,一个旋转的progressbar。但是只是这样的话,那么用户拉倒底部时候,只会调用
一次这个监听,并且刷新的图标一直在旋转,因此,用户体验差,那么可以通过下面代码完成

6.2 联网方式结束之后调用如下代码中一个

 myRecyclerAdapter.loadMoreComplete();
 //加载完成,这样每次加载完之后,progressbar都会消失了,当用户在滑到底部的时候就会在加载。
 myRecyclerAdapter.loadMoreEnd();
//加载结束,执行了这句代码之后,哪怕用户在滑动到底部,也不会走加载的方法了。
 myRecyclerAdapter.loadMoreFail();
//加载失败,这样在底部出现加载失败,点我重试字样,那么你点击之后可以重新加载。

6.3 myRecyclerAdapter.setEnableLoadMore(true);

这个方法是开启上拉刷新的关键方法。为了避免和下拉刷新出现冲突。

6.4 myRecyclerAdapter.setPreLoadNumber(3);

这个方法是设置预加载,比如这里设置了3,那么当用户滑到倒数第三条数据时候,就开始自动
走加载的方法,出现加载的动画。

6.5 可以使用自定义的加载布局

定义自定义类,使其继承LoadMoreView

public class myLoadMore extends LoadMoreView {
    //得到加载布局的id
    @Override
    public int getLayoutId() {
        return R.layout.load_more;
    }

    //得到加载的布局中用于加载的View的id
    @Override
    protected int getLoadingViewId() {
        return R.id.load_more_loading_view;
    }

    //得到加载的布局中用于展示加载失败的View的id
    @Override
    protected int getLoadFailViewId() {
        return R.id.load_more_load_fail_view;
    }
     //得到加载的布局中用于展示加载结束的View的id
    @Override
    protected int getLoadEndViewId() {
        return R.id.load_more_load_end_view;
    }
}

关于布局,里面最好包含三种情况,加载中,加载结束,加载失败。需要注意的是,你布局展示成多高,
那么加载的时候就会有多高,另外,最好是加载结束或者加载失败弄成gone,不弄也没事。

mQuickAdapter.setLoadMoreView(new MyLoadMore());

七、下拉加载

7.1 设置开启下拉刷新

myRecyclerAdapter.setUpFetchEnable(true);

7.2

myRecyclerAdapter.setUpFetchListener(new BaseQuickAdapter.UpFetchListener() {
            @Override
            public void onUpFetch() {
                Log.d("xljnewstudy", "进入了下拉加载更多");
            }
        });

此方法有一个弊端,如果你一直停在RecyclerView的顶部,那么它就会一直走记载的方法,所以需要你去
设置啥时候开启,另外,下拉刷新的时候不带有动画,所以,建议换一个下拉刷新的框架。

八、多套布局

8.1 实体类

实体类必须额外添加一个字段,用于区分这是什么样式。

在原来基础上添加
    private int itemType;
 
    public int getItemType() {
        return itemType;
    }

    public void setItemType(int itemType) {
        this.itemType = itemType;
    }

8.2 适配其中操作

由于是多套布局,因此不能像前面一样,还是选择布局加数据源参数的构造了,而是采用

public MyRecyclerViewAdpter(@Nullable List data) {
        super(data);
        setMultiTypeDelegate(new MultiTypeDelegate() {
            @Override
            protected int getItemType(myBenn myBenn) {
                return myBenn.getItemType();
// 这里需要返回每一个实体类中关键type,用于区分。
            }
        });

 getMultiTypeDelegate().registerItemType(1,R.layout.recycler_item)
                .registerItemType(2,R.layout.recycer_itemm_2)
                .registerItemType(3,R.layout.recyceler);
//表示可以继续添加很多个布局,在这里将标志type和不同的布局关联起来。
    }

在convert类中,在配置数据源时候,可以如下所示;

switch (helper.getItemViewType()){
            case 1:
                helper.setText(R.id.textView_my_name,item.getName());
                helper.setText(R.id.textView_my_age,item.getAge());
                break;

            case 2:
                helper.setText(R.id.textView_my_name,item.getName());
                helper.setText(R.id.textView_my_age,item.getAge());
                break;
          
             case  3:
             break;
        }

8.3 说明

当然了,你别忘了不同的布局。

九、滑动删除、拖动

9.1 完成这个需要重写Adapter,使其继承BaseItemDraggableAdapter


public class MyAdapter extends BaseItemDraggableAdapter {
    public MyAdapter(List data) {
        super(data);
    }

    public MyAdapter(int layoutResId, List data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, myBenn item) {
        helper.setText(R.id.textView_my_name,item.getName());
        helper.setText(R.id.textView_my_age,item.getAge());
    //和上面的差不多。正常的配置就好
    }
}

9.2 配置

建立RecyclerView,建立联系等等一系列操作,都和上面一样。

9.3 设置滑动删除、拖拽

        //下面是拖拽的代码
        ItemDragAndSwipeCallback itemDragAndSwipeCallback = new ItemDragAndSwipeCallback(mMyAdapter);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemDragAndSwipeCallback);
        itemTouchHelper.attachToRecyclerView(mRecyclerView);

         // 开启拖拽,上面R.id.textView_my_name 是表示你按住这个控件才可以实现拖拽
        mMyAdapter.enableDragItem(itemTouchHelper, R.id.textView_my_name, true);
        mMyAdapter.setOnItemDragListener(new OnItemDragListener() {
            @Override
            public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos) {

            }

            @Override
            public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {

            }

            @Override
            public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {

            }
        });

       // 开启滑动删除
        mMyAdapter.enableSwipeItem();
        mMyAdapter.setOnItemSwipeListener(new OnItemSwipeListener() {
            @Override
            public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {

            }

            @Override
            public void clearView(RecyclerView.ViewHolder viewHolder, int pos) {

            }

            @Override
            public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) {

            }

            @Override
            public void onItemSwipeMoving(Canvas canvas, RecyclerView.ViewHolder viewHolder, float dX, float dY, boolean isCurrentlyActive) {

            }
        });

//配置完上述,具体方法里面都不用写,就可以完成滑动删除,拖拽位置。

9.4 说明

如果针对于多套布局,默认是不能删除的,如果你想可以多套布局中也添加了删除,

public class myyy extends ItemDragAndSwipeCallback
{
    public myyy(BaseItemDraggableAdapter adapter) {
        super(adapter);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
        return true;
    }
}

即自己定义一个类,使其继承ItemDragAndSwipeCallback,然后重写onMove方法就好了。

总结

这个库还是不错的,建议,感兴趣的可以直接去Git上详细的了解,上面的只是我看到的一些,肯定还有所
不足。

你可能感兴趣的:(RecyclerView之学习使用BRVAH框架)