优秀的RecyclerView框架

   优点

优化Adapter代码:
和原始的adapter相对,减少70%的代码量。

添加Item事件:
Item的点击事件
Item的长按事件
Item子控件的点击事件
Item子控件的长按事件

添加列表加载动画:
一行代码轻松切换5种默认动画。

添加头部、尾部:
一行代码搞定,感觉又回到ListView时代。

自动加载:
上拉加载无需监听滑动事件,可自定义加载布局,显示异常提示,自定义异常提示。同时支持下拉加载。

分组布局:
随心定义分组头部。

多布局:
简单配置、无需重写额外方法。

设置空布局:
比Listview的setEmptyView还要好用。
添加拖拽、滑动删除:
开启,监听即可,就是这么简单。

树形列表:
比ExpandableListView还要强大,支持多级。

自定义ViewHolder:
支持自定义ViewHolder,让开发者随心所欲。

扩展框架:
组合第三方框架,轻松实现更多需求定制。

   导包

在project的gradle中
    allprojects {
        repositories {
            ...
            maven { url "https://jitpack.io" }
        }
    }

在module的gradle中
    dependencies {
            implementation'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30'
    }

混淆

-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 {
     <init>(...);
}

普通adapter

1.网络权限
2.添加recyclerview的兼容包
 implementation 'com.android.support:recyclerview-v7:26.1.0'
3.picasso
    implementation'com.squareup.picasso:picasso:2.5.2'
4.继承于BaseQuickAdapter<数据类,BaseViewHoloder>
public class HomeAdapter extends BaseQuickAdapter<Data,BaseViewHolder> {
    public HomeAdapter(@LayoutRes int layoutResId, @Nullable List<Data> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, Data item) {
        helper.setText(R.id.item_tv,item.getName());
        //通过helper.getView获取Imageview
        Picasso.with(mContext).load(item.getUrl()).into((ImageView) helper.getView(R.id.item_iv));
    }
}
5.使用
public class MainActivity extends AppCompatActivity {

    String url="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=532808234,3202881386&fm=27&gp=0.jpg";
    private RecyclerView rv;

    List<Data> datas;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
        initView();

    }

    private void initData() {
        datas=new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            Data data = new Data();
            data.setName("小埋"+i);
            data.setUrl(url);
            datas.add(data);
        }
    }

    private void initView() {
        rv = (RecyclerView) findViewById(R.id.rv);
        HomeAdapter homeAdapter = new HomeAdapter(R.layout.item, datas);
        rv.setAdapter(homeAdapter);
        rv.setLayoutManager(new LinearLayoutManager(this));
    }
}

添加点击事件

        homeAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                Toast.makeText(getApplicationContext(),"点击",Toast.LENGTH_SHORT).show();
                Log.v("meee",getClass()+":\n"+"点击");
            }
        });
        homeAdapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {
            @Override
            public boolean onItemLongClick(BaseQuickAdapter adapter, View view, int position) {
                Toast.makeText(getApplicationContext(),"长按",Toast.LENGTH_SHORT).show();
                Log.v("meee",getClass()+":\n"+"长按");
                //表示是否拦截点击事件,返回false则同时响应长按和点击两个事件
                return true;
            }
        });

添加子控件的点击事件

//在BaseQuickAdapter的点击事件中
    @Override
    protected void convert(BaseViewHolder helper, Data item) {
        //在helper中添加点击事件,支持链式调用
        helper.setText(R.id.item_tv,item.getName())
                .addOnClickListener(R.id.item_tv);
    }

//在页面中添加事件的回调
        homeAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                Log.v("meee",getClass()+":\n"+"view:"+view.getId());
            }
        });
添加子控件的长按点击事件:

adapter中绑定方法将addOnClickListener改成addOnLongClickListener.
设置点击事件方法setOnItemChildClickListener改成setOnItemChildLongClickListener
注意只有在adapter中绑定才有效果

列表添加时的动画效果

//开启动画效果,不传入则默认渐显;ALPHAIN渐显,SCALEIN 缩放,SLIDEIN_BOTTOM 从下到上,从左到右 SLIDEIN_LEFT,SLIDEIN_RIGHT 从右到左
        homeAdapter.openLoadAnimation(BaseQuickAdapter.SCALEIN);
//自定义动画
        homeAdapter.openLoadAnimation(new BaseAnimation() {
            @Override
            public Animator[] getAnimators(View view) {
                return new Animator[]{
                        ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1),
                        ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1)
                };
            }
        });

//默认只执行一次,有需要可设置
homeAdapter.isFirstOnly(false);

添加Header Footer Empty

        //添加头布局和脚布局
        homeAdapter.addHeaderView(new SeekBar(this));
        homeAdapter.addFooterView(new Switch(this));
        //添加空布局,默认出现了头部就不会显示Empty,和尾部,配置以下方法也支持同时显示
        homeAdapter.setEmptyView(new SeekBar(this));
        //默认头部尾部都是占满一行,如果需要不占满可以配置
        homeAdapter.setHeaderViewAsFlow(true);
        homeAdapter.setFooterViewAsFlow(true);

上拉和下拉刷新

        //上拉刷新,如果上拉结束后,下拉刷新需要再次开启上拉监听,需要使用setNewData方法填充数据。
        homeAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
            @Override
            public void onLoadMoreRequested() {
/*                //加载完成
                homeAdapter.loadMoreComplete();
                //加载失败
                homeAdapter.loadMoreFail();
                //加载结束
                homeAdapter.loadMoreEnd();*/
            }
        });
        //预加载
        // 当列表滑动到倒数第N个Item的时候(默认是1)回调onLoadMoreRequested方法
        homeAdapter.setPreLoadNumber(5);
        //自定义上拉刷新布局
        homeAdapter.setLoadMoreView(new CustomLoadMoreView());
  • 义的上拉刷新布局
    public final class CustomLoadMoreView extends LoadMoreView {
        //返回的是自定义的布局
        @Override public int getLayoutId() {
            return R.layout.item;
        }

        /**
         * 如果返回true,数据全部加载完毕后会隐藏加载更多
         * 如果返回false,数据全部加载完毕后会显示getLoadEndViewId()布局
         */
        @Override public boolean isLoadEndGone() {
            return true;
        }

        @Override protected int getLoadingViewId() {
            return R.id.load_more_loading_view;
        }

        @Override protected int getLoadFailViewId() {
            return R.id.load_more_load_fail_view;
        }

        /**
         * isLoadEndGone()为true,可以返回0
         * isLoadEndGone()为false,不能返回0
         */
        @Override protected int getLoadEndViewId() {
            return 0;
        }
    }

下拉刷新

        //开启下拉刷新>>>在第一个item展示的时候刷新,
        homeAdapter.setUpFetchEnable(true);
        homeAdapter.setUpFetchListener(new BaseQuickAdapter.UpFetchListener() {
            @Override
            public void onUpFetch() {
                Log.v("meee",getClass()+":\n"+"开始刷新");
                rv.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        homeAdapter.addData(0, datas);
                        //结束当前刷新,可以开始下次刷新
                        homeAdapter.setUpFetching(false);
                        //刷新结束后,item展示的位置
                        rv.scrollToPosition(datas.size());
                    }
                },2000);
            }
        });
        //开始加载的位置
        homeAdapter.setStartUpFetchPosition(10);

组合头布局

public class SectionAdapter extends BaseSectionQuickAdapter<MySection> {
     public SectionAdapter(int layoutResId, int sectionHeadResId, List data) {
        super(layoutResId, sectionHeadResId, data);
    }
    @Override
    protected void convert(BaseViewHolder helper, MySection item) {
        helper.setImageUrl(R.id.iv, (String) item.t);
    }
    @Override
    protected void convertHead(BaseViewHolder helper,final MySection item) {
        helper.setText(R.id.header, item.header);

        helper.setOnClickListener(R.id.more, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context,item.header+"more..",Toast.LENGTH_LONG).show();
            }
        });
    }

组合布局

//多类型布局需要实现MultiItemEntity,返回的不是int 布局类型
public class MutilData implements MultiItemEntity{
    public static final int TEXT=0;
    public static final int IMAGE=1;
    public int ItemType;
    String name;
    String url;

    public MutilData(int itemType) {
        ItemType = itemType;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    @Override
    public int getItemType() {
        return ItemType;
    }
}
//Mutil的英文打错了....吃了英语不好的亏233333
public class MutilAdapter extends BaseMultiItemQuickAdapter<MutilData,BaseViewHolder> {
    public MutilAdapter(List<MutilData> data) {
        super(data);
        //调用addItemType方法,传入不同类型和不同布局
        addItemType(MutilData.TEXT, R.layout.quick_view_load_more);
        addItemType(MutilData.IMAGE, R.layout.item);
    }

    @Override
    protected void convert(BaseViewHolder helper, MutilData item) {
        //通过helper.getItemViewType获取当前的数据类的type
        switch (helper.getItemViewType()){
            case MutilData.TEXT:
                break;
            case MutilData.IMAGE:
                helper.setText(R.id.item_tv,item.getName())
                        .addOnClickListener(R.id.item_tv);
                Picasso.with(mContext).load(item.getUrl()).into((ImageView) helper.getView(R.id.item_iv));
                break;
        }
    }
}

拖拽移动和滑动删除效果

//adapter继承于BaseItemDraggableAdapter
public class DradDeleteAdapter extends BaseItemDraggableAdapter<Data,BaseViewHolder> {
    public DradDeleteAdapter(int layoutResId, List<Data> data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, Data item) {
        helper.setText(R.id.item_tv,item.getName())
                .addOnClickListener(R.id.item_tv);
        Picasso.with(mContext).load(item.getUrl()).into((ImageView) helper.getView(R.id.item_iv));
    }
}
    //拖拽移动和滑动删除
    private void DragAndDelete() {
        DradDeleteAdapter adapter = new DradDeleteAdapter(R.layout.item, datas);
        //事件的回调类
        ItemDragAndSwipeCallback callback = new ItemDragAndSwipeCallback(adapter){
            @Override
            public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
                //返回true即可开启多个类型布局的拖拽
                return super.onMove(recyclerView, source, target);
            }
        };
        //通过ItemTouchHelper将rv和callback关联起来
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(rv);
        rv.setAdapter(adapter);

        //开启拖拽布局,第二个参数为点击的view可以拖动,第三个参数为true则长按拖动,false 点击拖动
        adapter.enableDragItem(itemTouchHelper, R.id.item_tv, true);
        // 开启右滑删除
        adapter.enableSwipeItem();
        //拖拽和滑动事件的监听回调
        OnItemDragListener onItemDragListener = 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) {}
        };
        adapter.setOnItemDragListener(onItemDragListener);

        OnItemSwipeListener onItemSwipeListener = 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) {

            }
        };
        adapter.setOnItemSwipeListener(onItemSwipeListener);
    }

自定义ViewHolder

创建BaseViewHolder的子类,static修饰,并将quickAdapter的第二个泛型改为自定义的类;
构造器和自定义的viewholder最好用public修饰

多级布局

层级数据类
//最后一级数据类,实现MultiItemEntity实现不同布局
public class Level0 implements MultiItemEntity {
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int getItemType() {
        return 0;
    }
}
//中间级,继承于AbstractExpandableItem<下一级的类为泛型>
public class Level4 extends AbstractExpandableItem<Level0> implements MultiItemEntity {
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //返回的层级
    @Override
    public int getLevel() {
        return 1;
    }

    @Override
    public int getItemType() {
        return 4;
    }
}
//最高级
public class Level5 extends AbstractExpandableItem<Level4> implements MultiItemEntity{
    String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    //返回的层级
    @Override
    public int getLevel() {
        return 0;
    }

    @Override
    public int getItemType() {
        return 5;
    }
}
    //构造数据类
    private ArrayList<MultiItemEntity> generateData() {

        int levelOne = 15;
        int levelTwo = 3;

        ArrayList<MultiItemEntity> res = new ArrayList<>();

        for (int i = 0; i < levelOne; i++) {
            Level5 lv5 = new Level5();
            for (int j = 0; j < levelTwo; j++) {

                Level4 lv4 = new Level4();
                //有一个addSubItem(T)方法,用于添加子数据,实现多级嵌套     
                lv4.addSubItem(new Level0());

                lv5.addSubItem(lv4);
            }
            res.add(lv5);
        }
        return res;
    }
继承于BaseMultiItemQuickAdapter<MultiItemEntity, BaseViewHolder>{
   public TreeAdapter(List<MultiItemEntity> data) {
        super(data);
        //不同布局,用法和组合布局相同
        addItemType(5, R.layout.item);
        addItemType(4, R.layout.quick_view_load_more);
        addItemType(0, simple_list_item_1);
    }

    @Override
    protected void convert(final BaseViewHolder holder, final MultiItemEntity item) {
        switch (holder.getItemViewType()) {
        //除了最后一级,处理都类似    
            case 5:
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //获取position
                        int pos = holder.getAdapterPosition();
                        holder.setText(R.id.item_tv,"哈哈");
                        //通过type来区分不同层级的数据item
                        Level5 l5=(Level5)item;
                        //通过AbstractExpandableItem.isExpanded()判断是否展开
                        if (l5.isExpanded()) {
                            //折叠子布局
                            collapse(pos);
                        } else {
                            //展开子布局
                            expand(pos);
                        }
                    }});
                break;
            //除了最后一级,处理都类似 
            case 4:
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        int pos = holder.getAdapterPosition();
                        Level4 l4=(Level4)item;
                        if (l4.isExpanded()) {
                            collapse(pos);
                        } else {
                            expand(pos);
                        }
                    }});
                break;
            //单纯的数据展示    
            case 0:
                holder.setText(android.R.id.text1,"位置");
                break;
        }
    }}

猜你喜欢

转载自blog.csdn.net/qq_42120002/article/details/80518626
今日推荐