Android recycleview拖放自定义功能



我正在尝试开发一个简单但自定义的recyclerview项目拖放功能。这个想法是将一个子视图拖到一个特定的视图,由FrameLayout表示,它不是recyclerview的子视图。当一个子元素被放到它上面时,它将被删除,否则它将简单地返回到原来的位置。我可以很容易地实现这种行为,而不需要任何动画效果,但我的目的是在UP dragevent和元素恢复上有平滑的动画。现在,每当一个子对象被拖拽时,我都会为它创建一个DragShadow,然后在数据集中删除该子对象,并使用adapter.notifyItemRemoved(position)通知移除。最后一个允许我有一个简单的删除动画由Recyclerview本身提供。代码将比文字更好地解释机制:

public boolean dragNdrop(View arg1, int position) {
    // ------------------------
    final RecyclerAdapter adapter= ListItemFragment.getAdapter();
   /*Keep track of the position and the object for restoring purpose*/
    ListItemFragment.indexAbruptedRemoved=position;
    ListItemFragment.itemAbruptedRemoved=adapter.getItem(position);
    ClipData clipData = ClipData.newPlainText("", "");
    View.DragShadowBuilder dsb = new View.DragShadowBuilder(arg1);
    arg1.startDrag(clipData, dsb, arg1, 0);

    adapter.remove(position);
    adapter.notifyItemRemoved(position);
    //--------------------
}

适配器getter方法:

protected static RecyclerAdapter getAdapter() {
        return (RecyclerAdapter) recList.getAdapter();
}

dragNdrop由自定义适配器中的拖动监听器调用:

public void onBindViewHolder(MyHolder myHolder, int position) {
   //----------------------------------
    myHolder.rowCard.setLongClickable(true);
    myHolder.rowCard.setOnClickListener(new MyClickListener.ContainerListener(context,
            myHolder.getAdapterPosition(), rowObject, myHolder.imagePreView));
    myHolder.rowCard.setOnLongClickListener(new MyClickListener.DragListener(context,
            myHolder.getAdapterPosition(), myHolder.rowCard));
 //----------------------------------
}

LongCLickListener:

static class DragListener implements View.OnLongClickListener {
    private Context context;
    private int position;
    private View dragged;
    DragListener(Context context, int position, View dragged) {
        this.context = context;
        this.position = position;
        this.dragged = dragged;
    }
    @Override
    public boolean onLongClick(View v) {
        return ((MainActivity) context).dragNdrop(dragged, position);
    }
}

名为trashPanel的framayout有以下代码:

 trashPanel.setOnDragListener(new View.OnDragListener() {

        @Override
        public boolean onDrag(View view, DragEvent dragEvent) {
            int dragAction = dragEvent.getAction();
            View dragView = (View) dragEvent.getLocalState();//this
            //is properly the object we 've passed with startdrag() 
            switch (dragAction) {
                case DragEvent.ACTION_DRAG_EXITED:
                    imageView.setImageDrawable(getResources().getDrawable(R.drawable.bowl));
                    break;
                case DragEvent.ACTION_DRAG_ENTERED:
                    imageView.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.waste));
                    break;
                case DragEvent.ACTION_DRAG_ENDED:
                    ended(view, dragEvent);
                    break;
                case DragEvent.ACTION_DROP:
                    Log.i(TAG,"HALOOOOO DROPPED");
                    drop();
                    break;
            }
            return true;
        }//[m] end on drag

        private void drop() {
            String itemToRemove = itemAbruptedRemoved.getSessionName();

            Toast.makeText(getActivity(), "DELETED: " + itemToRemove+
                            " list length:"+items.size()+" adapter length:"+mAdapter.size(),
                    Toast.LENGTH_SHORT).show();
            /**
             * HAPTIC FEEDBACK
             */
            Vibrator v = (Vibrator) getActivity().getSystemService(Service.VIBRATOR_SERVICE);
            long pattern[] = {25, 25, 50};
            v.vibrate(pattern, -1);// -1 to not repeat
        }
        private void ended(View view, DragEvent dragEvent) {
            if ( dropEventNotHandled(dragEvent) ) {
                mAdapter.insert(itemAbruptedRemoved, indexAbruptedRemoved);
                mAdapter.notifyItemInserted(indexAbruptedRemoved);
      //********---------->mAdapter.notifyDataSetChanged();
                Log.i(TAG,"AGGIUNTO");
            }
            //change the image inside trash_panel
            imageView.setImageDrawable(getActivity().getResources().getDrawable(R.drawable.bowl));
            //due to implementations detail it must be done in this way(otherwise mutithread exception is throwned)
            view.post(new Runnable() {
                public void run() {
                    /**
                     * Set animation for fabNew Button and trash_panel
                     * in order to make them smoothly disappear
                     * and place them in their original positions
                     *
                     */
                   ------------------------------------
                }
            });
        }

        private boolean dropEventNotHandled(DragEvent dragEvent) {
            return !dragEvent.getResult();
        }

    });

问题是,有时当我开始拖拽一个项目时,我获得了正确的DragShadow,但删除的项目是错误的。在代码中,我用***---->突出显示了对notifyDataSetChanged()的调用,因为如果我调用它,事情会正常工作,但没有动画。

我知道有实用程序类,如ItemTouchHelper。应该用来操作recyclelist子元素的运动和动画的回调,但是我不知道如何让它们做我想做的事情。我看到了几个方法,可以用来实现这一点,如onChildDrawOver和onChildDraw,但我仍然不知道如何使用它们来拦截dragevent。下降。我还知道LLM有一个名为ItemTouchHelper的接口。ViewDropHandler,有抽象方法prepareForDrop,但我仍然不知道如何使用它在一个适当的方式。

提前感谢所有帮助我的人!

看一下ItemTouchHelper。它将允许您自定义您的拖动绘图。参见Support7Demos获得一个示例实现。

最新更新