[Android]RecycleView的item用法

RecyclerView 是 Android 提供的一个强大的列表控件,用来显示大量数据。

RecyclerView 的主要特点

1. 高性能的视图复用机制

Recycle就是循环的意思,那么recycleview的特点也很鲜明了,它只会创建出在屏幕内和一定缓存的itemview,当view滑出屏幕时,不会销毁重建,而是复用旧的view,可以极高的提高性能;

2. 高度可定制

可以添加分割线、动画、拖拽、滑动删除;

3. 支持多种布局

支持线性、网格、瀑布流等布局实现;

子项的点击事件和长按点击事件

总体思路:因为我们在适配器的viewholder中可以拿到每个子项的view的,此时可以设置监听调用Onclick方法或者OnLongClick方法,然后通过接口回调的方式在RecycleView中设置回调的逻辑处理;

那么为什么要通过接口回调的方式呢?是因为适配器的任务就是绑定数据后显示UI,它不应该决定点击事件后的逻辑处理,所以在适配器中实现子项的监听,但是真正的实现我们放到Activity或者Fragment中,这样有利于解耦;

接下来看看具体的实现:

在适配器中:

Android 复制代码
private OnItemClickListener onItemClickListener;
public interface OnItemClickListener{
    void onItemClick(cityadapt cityadapt,int position);
    void onItemLongClick(cityadapt cityadapt,int position);
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
    this.onItemClickListener = onItemClickListener;
}
//实现接口,使得调用适配器中的Onclick的方法,然后再进行接口回调
public class cityviewholder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
public cityviewholder(@NonNull View itemView) {
    super(itemView);
     itemView.setOnClickListener(this);
}

    @Override
    public void onClick(View view) {
        if(onItemClickListener!= null){
            onItemClickListener.onItemClick(cityadapt.this,getAdapterPosition());
        }
    }

    @Override
    public boolean onLongClick(View view) {
        return true;
    }
}

在实现类中

Android 复制代码
cityadapt1.setOnItemClickListener(new cityadapt.OnItemClickListener() {
    @Override
    public void onItemClick(cityadapt cityadapt, int position) {
        viewPager2.setCurrentItem(position,true);
    }

    @Override
    public void onItemLongClick(cityadapt cityadapt, int position) {

    }
});

在进行子项的删除和拖动的学习之前,得先了解一个类:ItemTouchHelper

ItemTouchHelper

  • ItemTouchHelper 是 Android 官方提供的一个 RecyclerView 辅助类

  • 它通过 监听手势事件 ,帮助我们轻松实现:

    Item 拖动(上下或左右移动)

    Item 滑动(左滑/右滑删除,或执行其他操作)

  • 不需要自己去写复杂的手势检测逻辑。

我理解的本质也是接口回调,我们只定义接口的实现,然后作为构造方法的参数传入ItemTouchHelper的实例中,最后与RecycleView绑定;

在这里我们定义回调后的实现,比如允许滑动的方向等等;

Android 复制代码
ItemTouchHelper.Callback callback = new ItemTouchHelper.Callback() {
}

然后通过ItemTouchHelper的实例传入,使得后续做出自定义的逻辑判断和反应等;

Android 复制代码
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);

最后通过attachToRecyclerView与recycleview绑定,binding.recyCity是recycleview的实例;

Android 复制代码
itemTouchHelper.attachToRecyclerView(binding.recyCity);

ItemTouchHelper.Callback中有必须实现的三个抽象方法:

  • getMovementFlags():用来指定支持的拖拽和滑动方向

  • onMove():拖拽时回调(交换两个 item 的位置)

  • onSwiped():侧滑时回调(比如删除 item)

在本模块中介绍一下`getMovementFlags()

Android 复制代码
//规定可以滑动的方向
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
    int position = viewHolder.getAdapterPosition();
    if(position == 0){
        return 0;
    }
    int ver = 0;
    int hor = ItemTouchHelper.LEFT;
    return makeMovementFlags(ver,hor);
}
  • 最后返回一个方法makeMovementFlags(ver,hor),参数有两个,第一个是关于允许上下滑动或拖拽的,第二个是关于上下的;
Android 复制代码
int position = viewHolder.getAdapterPosition();
if(position == 0){
    return 0;
}

这里这么写得到当前滑动或者拖动的位置,如果这个是recycleview中第一个的话,就返回0,意味着不允许滑动或者拖拽;

  • ItemTouchHelper.LEFTItemTouchHelper.LEFTItemTouchHelper 里定义的一个常量,代表滑动(swipe)时允许的方向之一;

剩余的其他:

ItemTouchHelper.UP // 向上拖动

ItemTouchHelper.DOWN // 向下拖动

ItemTouchHelper.LEFT // 向左滑动

ItemTouchHelper.RIGHT // 向右滑动

子项的删除事件

ItemTouchHelper的基础上,我们还需重写一个方法:

Android 复制代码
//是否允许滑动移除
 @Override
 public boolean isItemViewSwipeEnabled() {
     return true;
 }

然后在ItemTouchHelper中的onSwiped方法内规定逻辑;

Android 复制代码
           //规定左滑后的逻辑
            @Override
            public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
                int i = viewHolder.getAdapterPosition();
                if(i != 0){
                    cityadapt1.getData().remove(i);
                    cityadapt1.notifyItemRemoved(i);
//                MainActivity.deleteFragment(i);
                    addtomainweather.deleteFragment(i);
                }
            }

里面有三个方法:

  • cityadapt1.getData().remove(i) : 把适配器中持有的数据源里对应的 item 移除;

  • cityadapt1.notifyItemRemoved(i):触发删除的动画;

  • addtomainweather.deleteFragment(i):通过接口回调的方式,自定义实现删除的逻辑;

当然我们也可以定义删除的动画

子项删除事件的动画效果

代码如下:

Android 复制代码
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    if(actionState == ItemTouchHelper.ACTION_STATE_SWIPE){
        View view = viewHolder.itemView;
        Paint paint = new Paint();
        paint.setColor(Color.WHITE);
        if(dX < 0){
           c.drawRect((float) view.getRight()+dX,(float) view.getTop(),(float) view.getRight(),(float) view.getBottom(),paint);
            Bitmap icon = BitmapFactory.decodeResource(recyclerView.getContext().getResources(),R.drawable.deletecity);
            int iconmargin =( view.getHeight() - icon.getHeight())/2;
            int top = view.getTop()+iconmargin;
            int bottom = top + icon.getHeight();
            int left = view.getRight() - iconmargin - icon.getWidth();
            int right =  view.getRight() - iconmargin;
            c.drawBitmap(icon,null,new Rect(left,top,right,bottom),null);
        }
    }
}

这个方法是 ItemTouchHelper.Callback 提供的 onChildDraw ,用来在 拖动/滑动时绘制额外的 UI 效果(比如背景、按钮、图标;

先看看这个方法对应的参数:

@NonNull Canvas c, // 画布

@NonNull RecyclerView recyclerView, // 当前的 RecyclerView

@NonNull RecyclerView.ViewHolder viewHolder, // 当前正在交互的 item

float dX, // X 方向的位移

float dY, // Y 方向的位移

int actionState, // 当前手势状态(滑动/拖动)

boolean isCurrentlyActive // 手指是否还在按住 item

代码中的部分说明:

actionState == ItemTouchHelper.ACTION_STATE_SWIPE是如果手势是滑动的话;

其他的滑动:

  • ItemTouchHelper.ACTION_STATE_IDLE → 没有操作

  • ItemTouchHelper.ACTION_STATE_DRAG → 拖动中

View view = viewHolder.itemView;获得当前的item;

c.drawRect((float) view.getRight()+dX,(float) view.getTop(),(float) view.getRight(),(float) view.getBottom(),paint); :里面有五个参数,分别是规定滑动后矩形的左边界,矩形的上边界,矩形的右边界,矩形的下边界,以及绘制的颜色/样式;

Bitmap icon = BitmapFactory.decodeResource(recyclerView.getContext().getResources(),R.drawable.deletecity);``recyclerView.getContext().getResources(),得到文件资源管理器,得到对应的图片等; BitmapFactory.decodeResource(Resources res, int id)BitmapFactory是一个解码工具类,这个方法会读取资源文件,并转成内存中的 Bitmap 对象

c.drawBitmap(icon,null,new Rect(left,top,right,bottom),null);四个参数分别代表:设置到画布上的bitmap对象,源区域(null代表设置整张图片),以及你要放置的位置,设置透明度等;

子项的拖动事件

重写此方法:

Android 复制代码
//是否允许长按拖拽
@Override
public boolean isLongPressDragEnabled() {
    return true;
}

此处跟删除的逻辑差不多,解释放在注释中,可自行观看;

Android 复制代码
            @Override
            public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
            //返回当前正在拖动的适配器中的数据索引
                  int i = viewHolder.getAdapterPosition();
                  //返回目标适配器中的数据索引
                  int j = target.getAdapterPosition();
                  //把适配器中持有的数据源里对应的 item 交换;
                  Collections.swap(cityadapt1.getData(),i,j);
                  //刷新item移动动画
                  cityadapt1.notifyItemMoved(i,j);
                  addtomainweather.swapFragment(i,j);
                  return true;
            }

            

这样我们就可以实现子项的点击事件,删除,拖动啦; --未完待续--

相关推荐
前行的小黑炭5 小时前
Android :为APK注入“脂肪”,论Android垃圾代码在安全加固中的作用
android·kotlin
帅得不敢出门6 小时前
Docker安装Ubuntu搭建Android SDK编译环境
android·ubuntu·docker
tangweiguo030519876 小时前
Android Kotlin 动态注册 Broadcast 的完整封装方案
android·kotlin
fatiaozhang95276 小时前
浪潮CD1000-移动云电脑-RK3528芯片-2+32G-安卓9-2种开启ADB ROOT刷机教程方法
android·网络·adb·电脑·电视盒子·刷机固件·机顶盒刷机
前行的小黑炭7 小时前
Android 不同构建模式下使用不同类的例子:如何在debug模式和release模式,让其使用不同的类呢?
android·kotlin·gradle
andyguo7 小时前
AI模型测评平台工程化实战十二讲(第一讲:从手工测试到系统化的觉醒)
android
2501_915921437 小时前
小团队如何高效完成 uni-app iOS 上架,从分工到工具组合的实战经验
android·ios·小程序·uni-app·cocoa·iphone·webview
幂简集成8 小时前
通义灵码 AI 程序员低代码 API 课程实战教程
android·人工智能·深度学习·神经网络·低代码·rxjava
2501_916008899 小时前
uni-app iOS 文件管理与 itools 配合实战,多工具协作的完整流程
android·ios·小程序·https·uni-app·iphone·webview