RecyclerView 拖放喜欢 - 文件和文件夹

Posted

技术标签:

【中文标题】RecyclerView 拖放喜欢 - 文件和文件夹【英文标题】:RecyclerView Drag and Drop like - FILE & FOLDER 【发布时间】:2018-05-05 23:36:10 【问题描述】:

现在我正在使用 RecyclerView 的 ItemTouchHelper.Callback 来重新排列回收站视图中项目的位置。

但现在我需要的是文件和文件夹的功能。

场景是文件和文件夹都是同一个回收站视图的项目。现在,当我将一个项目拖到一个文件夹上时,该文件夹不应从其位置移动,而是应接受源视图持有者作为其自身的子级。并且在它上面释放一个项目时,源视图持有者被隐藏并从回收者视图中删除。虽然文件夹仍然存在。

我在 Google 上搜索了很多,但无法为 Recycler View 找到此类行为的单一实现。

如果有人指导我应该处理什么,以获得此功能。

谢谢。

【问题讨论】:

你找到解决方案了吗?我需要像你这样的类似功能。找不到任何东西。 【参考方案1】:

使用ItemTouchHelper.SimpleCallback。它扩展了ItemTouchHelper.Callback,所以你以同样的方式将它附加到 RecyclerView。

您可以使用ItemTouchHelper.SimpleCallback 提供的默认项目拖动功能。 您还可以获得一些通知,这些通知将允许您实现放入文件夹。

以下课程将演示更改文件夹的背景颜色。一个项目将被拖放到该文件夹​​中。

您应该在描述的位置添加用于重新排序和删除项目(例如在 db 中)的代码。

class ItemDragAndDropCallback extends ItemTouchHelper.SimpleCallback 

    private final RecyclerView recyclerView;

    ItemDragAndDropCallback(RecyclerView recyclerView) 
        // Choose drag and swipe directions
        // Up and down is chosen for dragging
        // Nothing is chosen for swiping
        super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, 0);
        this.recyclerView = recyclerView;
    

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) 
        int from = viewHolder.getAdapterPosition();
        int to = target.getAdapterPosition();
        // You can reorder items here
        // Reorder items only when target is not a folder
        recyclerView.getAdapter().notifyItemMoved(from, to);
        return true;
    

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) 
        // You can react for swiping items here
        // Do nothing in your case
    

    // An item will be dropped into this folder
    private View folder;

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) 
        super.onSelectedChanged(viewHolder, actionState);

        if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) 

            // Here you are notified that the drag operation began

            if (folder != null) 
                folder.setBackgroundResource(0); // Clear former folder background
                folder = null;
            
         else if (actionState == ItemTouchHelper.ACTION_STATE_IDLE) 

            // Here you are notified that the last operation ended

            if (folder != null) 
                // Set folder background to a color indicating
                // that an item was dropped into it
                folder.setBackgroundColor(
                    ContextCompat.getColor(
                        recyclerView.getContext(), android.R.color.holo_green_dark
                    )
                );
                // You can remove item from the list here and add it to the folder
                // Remember to notify RecyclerView about it
                recyclerView.getAdapter().notifyItemRemoved(viewHolder.getAdapterPosition());
            
        
    

    // This method gets called a lot, so don't do any expensive operations here
    @Override
    public void onChildDraw(
        Canvas c,
        RecyclerView recyclerView,
        RecyclerView.ViewHolder viewHolder,
        float dX,
        float dY,
        int actionState,
        boolean isCurrentlyActive
    ) 
        if (actionState == ItemTouchHelper.ACTION_STATE_DRAG && isCurrentlyActive) 

            // Here you are notified that the drag operation is in progress

            if (folder != null) 
                folder.setBackgroundResource(0); // Clear former folder background
                folder = null;
            

            float itemActualPosition = viewHolder.itemView.getTop() + dY + viewHolder.itemView.getHeight() / 2;

            // Find folder under dragged item
            for (int i = 0; i < recyclerView.getChildCount(); i++) 
                View child = recyclerView.getChildAt(i);

                // Exclude dragged item from detection
                if (!child.equals(viewHolder.itemView)) 

                    // Accept folder which encloses item position
                    if (child.getTop() < itemActualPosition && itemActualPosition < child.getBottom()) 

                        folder = child;
                        // Set folder background to a color indicating
                        // that an item will be dropped into it upon release
                        folder.setBackgroundColor(
                            ContextCompat.getColor(
                                recyclerView.getContext(), android.R.color.holo_green_light
                            )
                        );
                        break;
                    
                
            
        
        super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
    

当您将项目拖到文件夹上时,项目下的文件夹背景将变为浅绿色。 当您将项目放入文件夹时,其背景将变为深绿色。

【讨论】:

我没有在“onSelectedChanged: 方法中访问recyclerView。我怎样才能得到recyclerView? 你必须将它作为构造函数参数传递。

以上是关于RecyclerView 拖放喜欢 - 文件和文件夹的主要内容,如果未能解决你的问题,请参考以下文章

在ANDROID中相互拖放时合并Recyclerview中的项目?

如何拖放 recyclerView 元素?

在 RecyclerView 中的特定位置拖放停止

拖放从 SQLiteDatabase 填充的 RecyclerView

拖放 RecyclerView 的第一项会移动几个随机位置

RecyclerView通过itemTouchHelper拖放快速拖动时很奇怪