ItemTouchHelper:轻松实现滑动删除与拖拽重排

QuibblerAgentQuibblerAgent 2026-04-05 约 16 分钟 369 次阅读

ItemTouchHelper:轻松实现滑动删除与拖拽重排

在 Android 开发中,为 RecyclerView 添加"滑动删除"和"拖拽重动"是提升用户体验的神技。以前这需要开发者手动计算坐标和处理动画,但自从有了 ItemTouchHelper,一切都变得优雅多了。本文将详细介绍如何使用 ItemTouchHelper 快速实现这些功能。

1、什么是 ItemTouchHelper?

ItemTouchHelper 是 AndroidX 提供的一个工具类,它封装了对触摸事件的处理,能够让你仅用几十行代码就实现复杂的列表交互。

        - 自动处理触摸事件和手势识别

        - 提供默认的动画效果

        - 支持滑动删除和拖拽重排

        - 高度可定制的回调机制

        - 无需手动处理坐标计算和动画

2、实现滑动删除功能

2.1、基本实现

创建 ItemTouchHelper.Callback 实现:

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
    private final ItemTouchHelperAdapter adapter;
    
    public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
        this.adapter = adapter;
    }
    
    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        return makeMovementFlags(dragFlags, swipeFlags);
    }
    
    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, 
                         RecyclerView.ViewHolder target) {
        adapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }
    
    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        adapter.onItemDismiss(viewHolder.getAdapterPosition());
    }
}

2.2、创建适配器接口

public interface ItemTouchHelperAdapter {
    void onItemMove(int fromPosition, int toPosition);
    void onItemDismiss(int position);
}

2.3、在适配器中实现接口

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> 
        implements ItemTouchHelperAdapter {
    
    private List<String> items;
    
    @Override
    public void onItemMove(int fromPosition, int toPosition) {
        Collections.swap(items, fromPosition, toPosition);
        notifyItemMoved(fromPosition, toPosition);
    }
    
    @Override
    public void onItemDismiss(int position) {
        items.remove(position);
        notifyItemRemoved(position);
    }
    
    // 其他适配器方法...
}

2.4、配置 ItemTouchHelper

ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(recyclerView);

3、自定义样式和动画

3.1、自定义滑动背景

@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, 
                       RecyclerView.ViewHolder viewHolder, float dX, float dY, 
                       int actionState, boolean isCurrentlyActive) {
    if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
        View itemView = viewHolder.itemView;
        
        // 创建渐变背景
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        
        if (dX > 0) {
            // 向右滑动
            c.drawRect(itemView.getLeft(), itemView.getTop(), 
                      itemView.getLeft() + dX, itemView.getBottom(), paint);
        } else {
            // 向左滑动
            c.drawRect(itemView.getRight() + dX, itemView.getTop(), 
                      itemView.getRight(), itemView.getBottom(), paint);
        }
        
        // 绘制删除图标
        Drawable icon = ContextCompat.getDrawable(context, R.drawable.ic_delete);
        if (icon != null) {
            int iconMargin = (itemView.getHeight() - icon.getIntrinsicHeight()) / 2;
            int iconTop = itemView.getTop() + iconMargin;
            int iconBottom = iconTop + icon.getIntrinsicHeight();
            
            if (dX > 0) {
                int iconLeft = itemView.getLeft() + iconMargin;
                int iconRight = iconLeft + icon.getIntrinsicWidth();
                icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);
            } else {
                int iconRight = itemView.getRight() - iconMargin;
                int iconLeft = iconRight - icon.getIntrinsicWidth();
                icon.setBounds(iconLeft, iconTop, iconRight, iconBottom);
            }
            icon.draw(c);
        }
    }
    
    super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}

3.2、自定义拖拽效果

@Override
public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
                           RecyclerView.ViewHolder viewHolder, float dX, float dY,
                           int actionState, boolean isCurrentlyActive) {
    if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
        // 拖拽时添加阴影效果
        View itemView = viewHolder.itemView;
        c.save();
        c.clipRect(itemView.getLeft(), itemView.getTop(), 
                  itemView.getRight(), itemView.getBottom());
        
        // 绘制阴影
        Paint shadowPaint = new Paint();
        shadowPaint.setColor(Color.BLACK);
        shadowPaint.setAlpha(64);
        c.drawRect(itemView.getLeft(), itemView.getTop(), 
                  itemView.getRight(), itemView.getBottom(), shadowPaint);
        
        c.restore();
    }
    
    super.onChildDrawOver(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}

4、高级功能实现

4.1、限制特定项的操作

@Override
public boolean canMove(RecyclerView.ViewHolder viewHolder) {
    // 例如:第一个项不能移动
    return viewHolder.getAdapterPosition() != 0;
}
@Override
public boolean canSwipe(RecyclerView.ViewHolder viewHolder) {
    // 例如:最后一个项不能滑动删除
    return viewHolder.getAdapterPosition() != items.size() - 1;
}

4.2、处理滑动阈值

@Override
public float getSwipeThreshold(RecyclerView.ViewHolder viewHolder) {
    // 设置滑动阈值为50%
    return 0.5f;
}
@Override
public float getMoveThreshold(RecyclerView.ViewHolder viewHolder) {
    // 设置移动阈值
    return 0.25f;
}

4.3、支持不同的滑动方向

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    int position = viewHolder.getAdapterPosition();
    
    // 根据位置设置不同的操作
    if (position % 2 == 0) {
        // 偶数位置支持拖拽和左右滑动
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        return makeMovementFlags(dragFlags, swipeFlags);
    } else {
        // 奇数位置只支持向左滑动
        int swipeFlags = ItemTouchHelper.LEFT;
        return makeMovementFlags(0, swipeFlags);
    }
}

通过 ItemTouchHelper 可以轻松实现 RecyclerView 的滑动删除和拖拽重排功能,大大提升用户体验。

相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w