Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do the list elements not swap?

I have a RecyclerView and have implemented an onMove command called onItemMove. I'm using onItemMove to try and get the list elements to swap position when dragged around, but the list elements just hover over each, they don't swap. How can I correct this?

Note 1: onItemDismiss works fine; it swipes the item away and removes it from the list.

Note 2: I've tried to Override onItemMove, but it doesn't actually override its superclass.

List Adaptor Class: This contains the onItemMove command

public class ListAdapter extends RecyclerView.Adapter<ListAdapter.ListViewHolder> {
    private static final String TAG = "ListAdapter";
    Context context;
    private List<UserData> dataList = new ArrayList<>();
    LayoutInflater inflater;
    Listener listener;
    DbHelper dbHelper;



    public interface Listener {
        void nameToChnge(String name);
    }

    public ListAdapter(Context context, List<UserData> dataList1) {
        this.context = context;
        this.dataList = dataList1;
        this.listener= (Listener) context;
        inflater = LayoutInflater.from(context);
    }


    @Override
    public ListViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View convertView = inflater.inflate(R.layout.recylerview_one, parent, false);
        ListViewHolder viewHolder = new ListViewHolder(convertView);
        return viewHolder;
    }

    @Override
    public void onBindViewHolder(ListViewHolder holder, final int position) {
        holder.tv_name.setText(dataList.get(position).name);
        holder.tv_quantity.setText(dataList.get(position).quantity);
        holder.tv_description.setText(dataList.get(position).description + "");

        holder.relLayout.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String s = dataList.get(position).id;
                Integer stringo = Integer.parseInt(s);
                Intent intent = new Intent(context, ItemEditActivity.class);
                intent.putExtra("ItemNumber", stringo);
                context.startActivity(intent);
            }
        });
    }

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

    class ListViewHolder extends RecyclerView.ViewHolder {
        TextView tv_name, tv_quantity, tv_description;
        RelativeLayout relLayout;


        public ListViewHolder(View itemView) {
            super(itemView);
            tv_name = (TextView) itemView.findViewById(R.id.nameDisplay);
            tv_quantity = (TextView) itemView.findViewById(R.id.quantityDisplay);
            tv_description = (TextView) itemView.findViewById(R.id.descriptionDisplay);
            relLayout = (RelativeLayout) itemView.findViewById(R.id.relLayout);
        }
    }



    public void onItemDismiss(final int position) {
        dataList.remove(position);
        notifyItemRemoved(position);

    }

    public void onItemMove(int fromPosition, int toPosition) {
        Collections.swap(dataList, fromPosition, toPosition);
        notifyItemMoved(fromPosition, toPosition);

    }
}

ItemTouchHelper Class:

  public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback{
        private final ListAdapter  mAdapter;


        public SimpleItemTouchHelperCallback(ListAdapter adapter) {
            mAdapter = adapter;
        }

        @Ov

erride
    public boolean isLongPressDragEnabled() {
        return true;
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        return true;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView,
                          RecyclerView.ViewHolder viewHolder,
                          RecyclerView.ViewHolder target) {
        mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());

        return true;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
        mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
    }
}

Part of the Main Activity where I initialise the RecyclerView and SimpleItemTouchHelperCallback:

public class MainActivity extends AppCompatActivity implements ListAdapter.Listener {
    private static final String TAG = "MainActivity";

    RecyclerView recyclerView;
    DbHelper dbHelper;
    ListAdapter adapter;
    FloatingActionButton fab;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        introItem();
        dbHelper = DbHelper.getInstance(getApplicationContext());

        recyclerView= (RecyclerView) findViewById(R.id.rv_contactlist);
        adapter = new ListAdapter(this, dbHelper.getAllUser());
        recyclerView.setAdapter(adapter);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));

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

        totalQuantity();

        adapter.notifyDataSetChanged();
        fabHideShow();
        versionCheckMethod();

    }
like image 668
Tom James Avatar asked Feb 25 '17 18:02

Tom James


People also ask

Can you swap items in a list Python?

Given a list in Python and provided the positions of the elements, write a program to swap the two elements in the list. Since the positions of the elements are known, we can simply swap the positions of the elements.

How do I swap a list in Python?

To swap two list elements x and y by value, get the index of their first occurrences using the list. index(x) and list. index(y) methods and assign the result to variables i and j , respectively. Then apply the multiple assignment expression lst[i], lst[j] = lst[j], lst[i] to swap the elements.

How do you swap two elements?

The first step is to create a temporary variable to hold the first element's value. The second step is to set the value of the first element to the value of the second element. The third step is to set the value of the second element to the value in the temporary variable.

How do you switch the first and last elements in a list?

Approach #5: Swap the first and last elements is to use the inbuilt function list. pop(). Pop the first element and store it in a variable. Similarly, pop the last element and store it in another variable.


1 Answers

You just need to study the code of this sample and implement it: https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/tree/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo

But basically what you need is to create two interfaces. The first one:

public interface ItemTouchHelperAdapter {
/**
 * Called when an item has been dragged far enough to trigger a move. This is called every time
 * an item is shifted, and not at the end of a "drop" event.
 *
 * @param fromPosition The start position of the moved item.
 * @param toPosition   Then end position of the moved item.

 */
void onItemMove(int fromPosition, int toPosition);


/**
 * Called when an item has been dismissed by a swipe.
 *
 * @param position The position of the item dismissed.

 */
void onItemDismiss(int position);
}

And the second one:

public interface ItemTouchHelperViewHolder {
    /**
      * Implementations should update the item view to indicate it's active state.
     */
    void onItemSelected();


    /**
     * state should be cleared.
     */
    void onItemClear();
}

The in the SimpleItemTouchHelperCallback something like that:

public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {

    private final ItemTouchHelperAdapter mAdapter;

    public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
        mAdapter = adapter;
    }

    @Override
    public boolean isLongPressDragEnabled() {
        return true;
    }

    @Override
    public boolean isItemViewSwipeEnabled() {
        return false;
    }

    @Override
    public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, swipeFlags);
    }

    @Override
    public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
        mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
        return true;
    }

    @Override
    public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) {
        mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
    }

    @Override
    public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
        if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
            ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
            itemViewHolder.onItemSelected();
        }

        super.onSelectedChanged(viewHolder, actionState);
    }

    @Override
    public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
        super.clearView(recyclerView, viewHolder);

        ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
        itemViewHolder.onItemClear();
    }
}

Then you have to change the RecyclerViewAdapter, and implement there the onItemMove method as we said in the oder comments. And you should implemement also the onStartDragListener like so:

    public interface OnStartDragListener {
    /**
     * Called when a view is requesting a start of a drag.
     *
     * @param viewHolder The holder of the view to drag.
     */
    void onStartDrag(RecyclerView.ViewHolder viewHolder);
}

And then use it in your adapter onBindViewHolder (remember to implement all the interfaces in the class declaration) like this (You need to change this code based on your variable name):

holder.handleView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
                    mDragStartListener.onStartDrag(holder);
                }
                return false;
            }
        });

Where mDragListener is a OnStartDragListener variable.

Finally check this guide for more: http://valokafor.com/remember-drag-and-drop-position-with-recyclerview/

like image 185
Angelo Parente Avatar answered Sep 28 '22 14:09

Angelo Parente