Android 回收视图拖放和;快速拖动时通过itemTouchHelper拖放

Android 回收视图拖放和;快速拖动时通过itemTouchHelper拖放,android,drag-and-drop,android-recyclerview,Android,Drag And Drop,Android Recyclerview,我一直在遵循这个链接的指南,在某些情况下我遇到了一些问题 所以,我基本上做了他解释的所有事情+我在item中添加了一个TextView,它表示一个项目在RecyclerView中的位置,类似这样: 一切看起来都很好,除了当我快速开始“吊带射击”物品时,我有两个问题: 它恰好有一个数字的副本。 我所做的还包括在 onItemClear()方法-它以某种方式修复了它,但导致 非法状态异常,被捕获-将导致 索引自动边界异常 局部地,当刷得太快时,物品进入“背景”。只有当项目大小不同时,才能看到这一

我一直在遵循这个链接的指南,在某些情况下我遇到了一些问题

所以,我基本上做了他解释的所有事情+我在item中添加了一个TextView,它表示一个项目在RecyclerView中的位置,类似这样:

一切看起来都很好,除了当我快速开始“吊带射击”物品时,我有两个问题:

  • 它恰好有一个数字的副本。

    我所做的还包括在
    onItemClear()
    方法-它以某种方式修复了它,但导致
    非法状态异常
    ,被捕获-将导致
    索引自动边界
    异常

  • 局部地,当刷得太快时,物品进入“背景”。只有当项目大小不同时,才能看到这一点。

  • 我将在下面粘贴我的整个适配器代码,其中一定有缺陷

    LayoutInflater inflater;
    Context context;
    AndroidEntityQuestionResult androidEntityQuestionResult;
    ArrayList<AndroidEntityAnswer> list = new ArrayList<>();
    ORDLayoutManagerQuestion ord;
    ScreenDimensionsConstants sdc;
    
    
    public OrderingRecycleAdapter(Context context, AndroidEntityQuestionResult androidEntityQuestionResult, ORDLayoutManagerQuestion ord) {
        inflater = LayoutInflater.from(context);
        this.context = context;
        this.list = androidEntityQuestionResult.getAndroidEntityQuestion().getEntityAnswer();
        this.androidEntityQuestionResult = androidEntityQuestionResult;
        this.ord = ord;
        sdc = new ScreenDimensionsConstants(context);
    }
    
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = inflater.inflate(R.layout.custom_row_ordering_rv, parent, false);
        final RecyclerView.ViewHolder holder = new OrderingViewHolder(view);
        return holder;
    }
    
    
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof OrderingViewHolder) {
    
            ((OrderingViewHolder) holder).answerText.setText(list.get(position).getAnswer().getANSWER_TEXT());
            int currentPosition = position + 1;
            ((OrderingViewHolder) holder).position.setText("#" + currentPosition);
        }
    }
    
    @Override
    public int getItemCount() {
        return list.size();
    }
    
    @Override
    public boolean onItemMove(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(list, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(list, i, i - 1);
            }
        }
        notifyItemMoved(fromPosition, toPosition);
        notifyItemChanged(fromPosition);
        return true;
    }
    
    @Override
    public void onItemDismiss(int position) {
    
    }
    
    @Override
    public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
            ord.getItemTouchHelper().startDrag(viewHolder);
    }
    
    class OrderingViewHolder extends RecyclerView.ViewHolder implements ItemTouchHelperViewHolder {
        private TextView answerText;
        private ImageView pin;
        private TextView position;
    
        public OrderingViewHolder(View itemView) {
            super(itemView);
            answerText = (TextView) itemView.findViewById(R.id.orderingAnswer);
            answerText.setTextSize(TypedValue.COMPLEX_UNIT_PX, sdc.getHeight() / 40);
    
            pin = (ImageView) itemView.findViewById(R.id.ordering_pin);
            pin.getLayoutParams().width = sdc.getHeight() / 15;
            pin.getLayoutParams().height = sdc.getHeight() / 15;
    
            pin.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (MotionEventCompat.getActionMasked(event) ==
                            MotionEvent.ACTION_DOWN) {
                        OrderingRecycleAdapter.this.onStartDrag(OrderingViewHolder.this);
                    }
                    return false;
                }
            });
            position = (TextView) itemView.findViewById(R.id.answer_position);
            position.setTextSize(TypedValue.COMPLEX_UNIT_PX, sdc.getHeight() / 40);
    
        }
    
        @Override
        public void onItemSelected() {
            itemView.setBackgroundResource(R.drawable.menu_item_background_ice_blue);
        }
    
        @Override
        public void onItemClear() {
            itemView.setBackgroundResource(R.drawable.menu_item_background_white);
            int currentPosition = getLayoutPosition() + 1;
            position.setText("#" + currentPosition);
           //notifyDataSetChanged();
    
        }
    }
    
    充气机;
    语境;
    AndroidEntityQuestionResult AndroidEntityQuestionResult;
    ArrayList=新建ArrayList();
    OrdLayoutManager问题ord;
    屏幕尺寸常数sdc;
    public OrderingRecycleAdapter(上下文上下文、AndroidEntityQuestionResult和AndroidEntityQuestionResult、OrdLayoutManager问题ord){
    充气器=充气器。从(上下文);
    this.context=上下文;
    this.list=androidEntityQuestionResult.getAndroidEntityQuestion().getEntityAnswer();
    this.androidEntityQuestionResult=androidEntityQuestionResult;
    这个.ord=ord;
    sdc=新屏幕尺寸约束(上下文);
    }
    @凌驾
    public RecyclerView.ViewHolder onCreateViewHolder(视图组父级,int-viewType){
    视图=充气机。充气(R.layout.custom\u row\u ordering\u rv,parent,false);
    final RecyclerView.ViewHolder=新订单ViewHolder(视图);
    报税表持有人;
    }
    @凌驾
    BindViewHolder上的公共无效(RecyclerView.ViewHolder,int位置){
    if(OrderingViewHolder的持有者实例){
    ((OrderingViewHolder)holder.answerText.setText(list.get(position.getAnswer().getAnswer_TEXT());
    int currentPosition=位置+1;
    ((OrderingViewHolder)holder.position.setText(“#”+当前位置);
    }
    }
    @凌驾
    public int getItemCount(){
    返回list.size();
    }
    @凌驾
    公共布尔onItemMove(int-fromPosition,int-toPosition){
    如果(从位置<位置){
    for(inti=fromPosition;itoPosition;i--){
    集合。交换(列表,i,i-1);
    }
    }
    已移动的项目(从位置、位置);
    通知项已更改(从位置);
    返回true;
    }
    @凌驾
    公共空间和公共空间(内部位置){
    }
    @凌驾
    开始拖动时的公共无效(RecyclerView.ViewHolder ViewHolder){
    ord.getItemTouchHelper().startDrag(viewHolder);
    }
    类OrderingViewHolder扩展了RecyclerView.ViewHolder实现ItemTouchHelperViewHolder{
    私有文本查看应答文本;
    私人图像查看pin;
    私有文本视图位置;
    public OrderingViewHolder(查看项目视图){
    超级(项目视图);
    answerText=(TextView)itemView.findViewById(R.id.orderingAnswer);
    answerText.setTextSize(TypedValue.COMPLEX\u UNIT\u PX,sdc.getHeight()/40);
    pin=(ImageView)itemView.findViewById(R.id.ordering\u pin);
    pin.getLayoutParams().width=sdc.getHeight()/15;
    pin.getLayoutParams().height=sdc.getHeight()/15;
    pin.setOnTouchListener(新视图.OnTouchListener(){
    @凌驾
    公共布尔onTouch(视图v,运动事件){
    if(MotionEventCompat.getActionMasked(事件)==
    MotionEvent.ACTION(下一步){
    OrderingRecycleAdapter.this.onStartDrag(OrderingViewHolder.this);
    }
    返回false;
    }
    });
    position=(TextView)itemView.findViewById(R.id.answer\u position);
    position.setTextSize(TypedValue.COMPLEX\u UNIT\u PX,sdc.getHeight()/40);
    }
    @凌驾
    已选定的公共文件(){
    itemView.setBackgroundResource(R.drawable.menu\u item\u background\u ice\u blue);
    }
    @凌驾
    公共许可证{
    itemView.setBackgroundResource(R.drawable.menu\u item\u background\u white);
    int currentPosition=getLayoutPosition()+1;
    position.setText(“#”+当前位置);
    //notifyDataSetChanged();
    }
    }
    
    奖金问题

    是否有任何关于在2个RecyclerViews之间拖放的教程或信息


    我知道有一个问题,但没有答案,我在这里可能更幸运

    在我看来,似乎您的onItemMove()并不能解释所有的更改。 当某物为多个项目移动时(比如在A和B之间),您正在两个项目之间交换所有项目。 但是,您只报告A&B的更改,而不报告中间的其余元素

    我建议您编写一个报告所有更改的交换方法:

    public boolean swapItems(int fromPosition, int toPosition){
        Collections.swap(list, fromPosition, toPosition);
        notifyItemMoved(fromPosition, toPosition);
        notifyItemMoved(toPosition, fromPosition);
        // And maybe also notifyItemChanged() as the item changes due to the shift
        notifyItemChanged(fromPosition);
        notifyItemChanged(toPosition);
    }
    

    调用此函数而不是Collections.swap(),并删除其余的notify代码

    更改您的ONIMMOVE方法

    @Override
    public boolean onItemMove(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(list, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(list, i, i - 1);
            }
        }
        notifyItemMoved(fromPosition, toPosition);
        notifyItemChanged(fromPosition);
        return true;
    }
    
    @覆盖
    公共布尔onItemMove(int-fromPosition,int-toPosition){
    如果(从位置<位置){
    for(inti=fromPosition;itoPosition;i--){
    集合。交换(列表,i,i-1);
    }
    }
    已移动的项目(从位置、位置);
    通知项已更改(从位置);
    返回true;
    }
    
    致:

    @覆盖
    公共布尔onItemMove(int-fromPosition,int-toPosition){
    如果(从位置<位置){
    for(inti=fromPosition;i@Override
    public boolean onItemMove(int fromPosition, int toPosition) {
        if (fromPosition < toPosition) {
            for (int i = fromPosition; i < toPosition; i++) {
                Collections.swap(list, i, i + 1);
            }
        } else {
            for (int i = fromPosition; i > toPosition; i--) {
                Collections.swap(list, i, i - 1);
            }
        }
        notifyItemMoved(fromPosition, toPosition);
        return true;
    }
    
    notifyItemChanged(fromPosition);
    notifyItemMoved(fromPosition, toPosition);
    notifyItemRangeChanged(fromPosition,toPosition)