饭后Android 第四餐-BRVAH(最好用的数据适配器)(BRVAH简介,使用方法,item的点击事件,列表加载动画,添加头部、尾部,自定义ViewHolder)

官方引言:Recyclerview作为Android最常用的控件之一,是否常常为“她”操碎了心
BRVAH受益群体是所有Android开发者,希望更多开发者能够一起来把这个项目做得更好帮助更多人

我的感受:学会了这个框架以后,在使用recyclerview上会大大节省时间,真的是大大节省时间奥,话不多说,干代码来

1.BRVAH简介

BRVAH是一个强大的RecyclerAdapter框架,它能节约开发者大量的开发时间,集成了大部分列表常用需求解决方案

官网地址
GitHub地址
BRVAH官方使用指南(持续更新)
推荐博主文章
1.开源框架BaseRecyclerViewAdapterHelper使用——RecyclerView万能适配器
在这里插入图片描述

BRVAH全称BaseRecyclerViewAdapterHelper,它是一款针对在recyclerview使用中节省开发者时间的开源框架,在以往的开发中,我们需要重写holder和adapter,而BRVAH将hodler和adapter进行了封装,且recyclerview的adapter用BRVAH来实现比起原生可以减少70%的代码量

2.使用方法

1.引入框架

    maven {
    
     url "https://jitpack.io" }

注意是在build.gradle(Project:XXXX) 的 repositories 添加:

在这里插入图片描述

然后在 build.gradle(Module:app) 的 dependencies 添加依赖:
在这里插入图片描述

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

官方作者提示:

更新说明:https://github.com/CymChad/BaseRecyclerViewAdapterHelper/releases

注意 版本:2.9.28 Change the method setVisible --> setGone The new method setVisible

setVisible:Set a view visibility to VISIBLE (true) or INVISIBLE
(false). setGone: Set a view visibility to VISIBLE (true) or GONE
(false).

注意: 一旦出现加载失败的情况,只有两种情况:

配置没配置好 配置没配置好,有几种情况:

  1. 只配置了dependencies
  2. 配置repositories,但是位置错了,build.gradle(Project:XXXX) 文件下的repositories有两个,一个是buildscript下面的,一个是allprojects下面的,要配置到allprojects下面才是对的。
  3. 版本号前面多一个v,这个是我的锅,在2.1.2版本之前都是带v的,之后(包含2.1.2)都不需要带v。 网络原因(这个就不解释了)

2.添加布局文件

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

   <androidx.recyclerview.widget.RecyclerView
       android:id="@+id/recyler"
       android:layout_width="match_parent"
       android:layout_height="match_parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

item.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="这是第1条数据"
        android:textSize="24sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="name:"
        android:textSize="16sp"

        app:layout_constraintStart_toStartOf="@+id/textView"
        app:layout_constraintTop_toBottomOf="@id/textView" />

    <TextView
        android:id="@+id/name2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/dp_10"
        android:text="小明"
        android:textSize="16sp"
        app:layout_constraintLeft_toRightOf="@id/name"
        app:layout_constraintTop_toBottomOf="@id/textView" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@drawable/head"
        android:layout_marginTop="@dimen/dp_10"
        app:layout_constraintEnd_toStartOf="@+id/textView"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />


    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="@dimen/dp_40"
        android:text="button"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textView" />

</androidx.constraintlayout.widget.ConstraintLayout>

3.创建实体类

Person类


public class Person {
    
    
    public int id;
    public String name;
   

    public int getId() {
    
    
        return id;
    }

    public void setId(int id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

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

    
}

4.编写适配器 ☆

重点!!!

首先需要继承BaseQuickAdapter,然后BaseQuickAdapter<Status,
BaseViewHolder>第一个泛型Status是数据实体类型,第二个BaseViewHolder是ViewHolder其目的是为了支持扩展ViewHolder

在这里插入图片描述
MyAdapter

public class MyAdapter extends BaseQuickAdapter<Person, BaseViewHolder> {
    
    

    public MyAdapter(@LayoutRes int layoutResId, @Nullable List<Person> data) {
    
    
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, Person item) {
    
    
        //可链式调用赋值
        helper.setText(R.id.textView, "第"+ item.getId() + "条数据")
                .setText(R.id.name2, item.getName())
                .setImageResource(R.id.imageView, R.drawable.head);

        //获取当前条目position
        //int position = helper.getLayoutPosition();
    }
}

5.MainActivity

在这里插入图片描述


public class MainActivity extends AppCompatActivity {
    
    
     RecyclerView recyclerView;
     List<Person> datas;
     MyAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView=findViewById(R.id.recyler);//实例化

        //模拟数据
        datas = new ArrayList<>();
        Person person;
        for (int i = 0; i < 15; i++) {
    
    
            person= new Person();
            person.setId(i);
            person.setName("第" + i + "条内容");
            datas.add(person);


        }
        //创建布局管理
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(layoutManager);

        //创建适配器
        adapter = new MyAdapter(R.layout.item, datas);

        //给RecyclerView设置适配器
        recyclerView.setAdapter(adapter);
        adapter.notifyDataSetChanged();
    }
}

这样,一个简单的recyclerview就编写完了

6.运行

在这里插入图片描述

我们可以对比与之前的recyclerview的写法,在使用框架之后,我们在holder和adpter省去了大量的代码

在这里插入图片描述

3.item的点击事件

1.Item的点击事件

注意要放在adpter创建后

  //item点击事件
        adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
    
    
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
    
    

                Toast.makeText(MainActivity.this, "点击了第" + (position + 1) + "条条目", Toast.LENGTH_SHORT).show();
            }
        });

2.Item的长按事件

        //条目长按事件
        adapter.setOnItemLongClickListener(new BaseQuickAdapter.OnItemLongClickListener() {
    
    
            @Override
            public boolean onItemLongClick(BaseQuickAdapter adapter, View view, int position) {
    
    

                Toast.makeText(MainActivity.this, "长按了第" + (position + 1) + "条条目", Toast.LENGTH_SHORT).show();
                return false;
            }
        });

在这里插入图片描述

3.Item的子控件点击事件

第一步,在adpter的convert里通过 helper.addOnClickListener 绑定一下子控件的控件id
(同理,长按是helper.addOnLongClickListener)
在这里插入图片描述

 .addOnClickListener(R.id.button)//给按钮添加点击事件

第二步,我们设置

        //条目子控件点击事件
        adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
    
    
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
    
    

                Toast.makeText(MainActivity.this, "点击了第" + (position + 1) + "条条目的按钮", Toast.LENGTH_SHORT).show();
            }
        });

.运行
在这里插入图片描述
注意:设置子控件的事件,如果不在adapter中绑定,点击事件无法生效,因为无法找到你需要设置的控件。

4.多个Item子控件事件

我们可以通过判断id来判定是否是我们所设置的控件
第一步,还是在adpter里添加点击事件(这里我们给图片添加点击事件)
在这里插入图片描述

.addOnClickListener(R.id.imageView)//给图片添加点击事件

第二步,在刚才的单个子控件里加上判断

//条目子控件点击事件
        adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
    
    
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
    
    

                //判断id
                if (view.getId() == R.id.button) {
    
    
                    Toast.makeText(MainActivity.this, "点击了第" + (position + 1) + "条条目的按钮", Toast.LENGTH_SHORT).show();
                } else if (view.getId() == R.id.imageView) {
    
    
                    Toast.makeText(MainActivity.this, "点击了第" + (position + 1) + "条条目的图片", Toast.LENGTH_SHORT).show();
                }

            }
        });

运行
在这里插入图片描述
注意:如果有header的话需要处理一下position加上 headerlayoutcount。

4.列表加载动画

1.开启动画(默认为渐显效果)

//开启动画(默认为渐显效果)
adapter.openLoadAnimation();

2.该适配器提供了5种动画效果(渐显、缩放、从下到上,从左到右、从右到左)

·public static final int ALPHAIN = 0x00000001;//渐显
    public static final int SCALEIN = 0x00000002;//缩放
    public static final int SLIDEIN_BOTTOM = 0x00000003;//从下到上
    public static final int SLIDEIN_LEFT = 0x00000004;//从左到右
    public static final int SLIDEIN_RIGHT = 0x00000005;//从右到左

3.更换动画效果

//使用缩放动画
adapter.openLoadAnimation(BaseQuickAdapter.SCALEIN);

4.运行(动图不是很明显,建议亲手运行)
在这里插入图片描述

5.如果想自定义动画,该适配器也提供了接口

        //自定义动画效果
        adapter.openLoadAnimation(new BaseAnimation() {
    
    
            @Override
            public Animator[] getAnimators(View view) {
    
    
                return new Animator[]{
    
    
                        ObjectAnimator.ofFloat(view, "scaleY", 1, 0.5f, 1),
                        ObjectAnimator.ofFloat(view, "scaleX", 1, 0.5f, 1)
                };
            }
        });

6.动画默认只执行一次,如果想重复执行可设置

//设置重复执行动画
adapter.isFirstOnly(false);

7.首次到界面的item每次都依次执行加载动画

由于进入界面的item都是很多的速度进来的所以不会出现滑动显示的依次执行动画效果,这个时候会一起执行动画,如果觉得这样的效果不好可以使用setNotDoAnimationCount设置第一屏item不执行动画,但是如果需要依次执行动画可以重写startAnim让第一个屏幕的item动画延迟执行即可。

@Override
    protected void startAnim(Animator anim, int index) {
    
    
        super.startAnim(anim, index);
        if (index < count)
        anim.setStartDelay(index * 150);
    }

5.添加头部、尾部

在这里插入图片描述
添加

  View header = getLayoutInflater().inflate(R.layout.header, (ViewGroup) recyclerView.getParent(), false);
        View footer = getLayoutInflater().inflate(R.layout.footer, (ViewGroup) recyclerView.getParent(), false);
        adapter.addHeaderView(header);
        adapter.addFooterView(footer);

header.xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="20dp"
    android:background="#29B6F6">

</androidx.constraintlayout.widget.ConstraintLayout>

footer.xml布局文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="20dp"
    android:background="#EC407A">

</androidx.constraintlayout.widget.ConstraintLayout>

删除指定view

adapter.removeHeaderView(header);
adapter.removeFooterView(footer);

删除所有

 adapter.removeAllHeaderView();
 adapter.removeAllFooterView();

默认出现了头部就不会显示Empty,和尾部,配置以下方法也支持同时显示:

setHeaderAndEmpty
setHeaderFooterEmpty

默认头部尾部都是占满一行,如果需要不占满可以配置:

setHeaderViewAsFlow
setFooterViewAsFlow

6.添加拖拽、滑动删除

这里adapter需要继承BaseItemDraggableAdapter
在这里插入图片描述
activity代码
在这里插入图片描述

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

        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 v, float v1, boolean b) {
    
    

            }
        };


        ItemDragAndSwipeCallback itemDragAndSwipeCallback = new ItemDragAndSwipeCallback(adapter);
        ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemDragAndSwipeCallback);
        itemTouchHelper.attachToRecyclerView(recyclerView);

// 开启拖拽
        adapter.enableDragItem(itemTouchHelper, R.id.item, true);
        adapter.setOnItemDragListener(onItemDragListener);

// 开启滑动删除
        adapter.enableSwipeItem();
        adapter.setOnItemSwipeListener(onItemSwipeListener);

在这里插入图片描述

7.自定义ViewHolder

需要继承BaseViewHolder

 public class MyViewHolder extends BaseViewHolder {
    
    
        private TextView mTextView;
        public MyViewHolder(View view) {
    
    
            super(view);
        }
    }

然后修改adapter的第二个泛型为自定义的ViewHolder
在这里插入图片描述
注意:需要单独建一个外部类继承BaseViewHolder,否则部分机型会出现ClassCastException,如果是内部类的构造方法要是public,定义的那个类也最好是public。

8.设置空布局

// 没有数据的时候默认显示该布局
mQuickAdapter.setEmptyView(getView());

在这里插入图片描述
关于BRVAH官方文档中还介绍了上拉加载,和分组布局以及多布局的用法,大家也可以去研究。

8.拓展框架

作者谈:
由于adapter本身能力有限,我们又不想耦合view层所以有些需求是现实不了,于是合作了一些优秀开源库,为开发者提供更多可能性。以下扩展框架都是有结合BRVAH的demo。

关于BRVAH的介绍就讲到这里啦,是不是感觉开发又轻松了一点呢
博主为了可以学到更多的Android知识,创建了一个安卓知识交流群,欢迎大佬入群,当然也欢迎和我一样的安卓小白,我们可以一起交流,最重要的是快乐水群,记得定个小目标,冲击bat

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46526828/article/details/109146552