Search code examples
javaandroidandroid-recyclerviewdrag-and-drop

How to set Item position in order after using ItemTouchHelper.Callback


I am creating a document arrangement activity with RecyclerView. I want to arrange the document with drag and drop. It was done by using ItemTouchHelper.Callbackbut after that I can't set the page number after the OnItemMove callback. what should I do?

EDIT: added code snippet

package adapters;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.pdf.PdfRenderer;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;

import com.mobilix.docscanner.R;

import java.util.ArrayList;
import java.util.Collections;

import helper.ItemTouchHelperAdapter;
import helper.ItemTouchHelperViewHolder;
import helper.OnStartDragListener;
import helper.SimpleItemTouchHelperCallback;

public class PageAjdustAdapter extends RecyclerView.Adapter<PageAjdustAdapter.PageAdjustHolder> implements ItemTouchHelperAdapter, OnStartDragListener {
    private final String TAG = getClass().getName();
    Context mContext;
    ArrayList<PdfPage> pdfPages = new ArrayList<>();
    private ItemTouchHelper itemTouchHelper;

    public PageAjdustAdapter(Context context, ArrayList<PdfPage> pages) {
        this.mContext = context;
        pdfPages = pages;


        ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(this);
        itemTouchHelper = new ItemTouchHelper(callback);
        itemTouchHelper.attachToRecyclerView(((Activity) context).findViewById(R.id.rcvPageArrange));

    }

    @NonNull
    @Override
    public PageAdjustHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(mContext).inflate(R.layout.item_page_adajustment, parent, false);
        return new PageAdjustHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull PageAdjustHolder holder, int position) {
        Log.d(TAG, "onBindViewHolder: ");
        holder.ivPage.setImageBitmap(pdfPages.get(position).bitmap);
        holder.cbPage.setChecked(pdfPages.get(position).isSelected);
        holder.tvPageNo.setText(String.valueOf(position + 1));

        holder.cbPage.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                pdfPages.get(holder.getAdapterPosition()).isSelected = isChecked;
            }
        });

        holder.ivRotate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = holder.getAdapterPosition();
                pdfPages.get(pos).bitmap = Bitmap.createBitmap(//
                        pdfPages.get(pos).bitmap, 0, 0, pdfPages.get(pos).bitmap.getWidth(),//
                        pdfPages.get(pos).bitmap.getHeight(), pdfPages.get(pos).matrix, true);//

                notifyItemChanged(pos);
            }
        });
    }

    @Override
    public int getItemCount() {
        return pdfPages.size();
    }

    @Override
    public boolean onItemMove(int fromPosition, int toPosition) {
        Log.d(TAG, "onItemMove: ->fp " + (fromPosition + 1) + " tp-> " + (toPosition + 1));
        Collections.swap(pdfPages, fromPosition, toPosition);
        notifyItemMoved(fromPosition, toPosition);

        
        return false;
    }

    @Override
    public void onItemDismiss(int position) {
        pdfPages.remove(position);
        notifyItemRemoved(position);
    }

    @Override
    public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
        itemTouchHelper.startDrag(viewHolder);

    }


    public static class PageAdjustHolder extends RecyclerView.ViewHolder implements
            ItemTouchHelperViewHolder {
        ImageView ivPage, ivRotate;
        CheckBox cbPage;
        TextView tvPageNo;

        public PageAdjustHolder(@NonNull View itemView) {
            super(itemView);
            ivPage = itemView.findViewById(R.id.ivPage);
            ivRotate = itemView.findViewById(R.id.ivRotate);
            cbPage = itemView.findViewById(R.id.cbPage);
            tvPageNo = itemView.findViewById(R.id.tvPageNo);
        }

        @Override
        public void onItemSelected() {

        }

        @Override
        public void onItemClear() {

        }
    }

    public static class PdfPage {
        PdfRenderer.Page page;
        Bitmap bitmap;
        boolean isSelected;
        Matrix matrix;
        int rotate = 0;

        public PdfPage(PdfRenderer.Page page, Bitmap bitmap) {
            this.page = page;
            this.bitmap = bitmap;
            matrix = new Matrix();
            rotate += 90;
            matrix.postRotate(90);//martix work on +=90
        }
    }

}

Solution

  • You have to call notifyDataSetChanged() when an item position is changed. The easiest way it to used onItemClear(), it will be called when an item is de-selected. Add it like following.

        @Override
        public void onItemClear() {
              notifyDataSetChanged();
        }
    

    One thing you have to add is check weather the position is actually changed after the drag operation or not other wise it will always update the whole dataset whenever an item is selected and than de-selected.

    Edit

    Create a local variable in view-holder class. Than you just have to set it in onItemSelected() and check it in onItemClear();

        @Override
        public void onItemSelected() {
            lastpos = getAdapterPosition();
        }
    
    
        @Override
        public void onItemClear() {
             if(lastpos != getAdapterPosition())
                  notifyDataSetChanged();
        }