I have a recyclerview and an imageview. I want to be able to drag an item from the list over the top of the imageview (and later on drop it). The problem is that when i drag the item it goes underneath the image not over it.
section from activity
private void updateRecycler(RecyclerView myrecyclerview)
{
RecyclerView r = myrecyclerview;
itemsAdapter=new skutest_recyclerview_viewadapter(itmlist);
runOnUiThread(() -> {
if (r.getLayoutManager()==null)
{
r.setLayoutManager(new LinearLayoutManager(MainActivity.this));
}
r.setAdapter(itemsAdapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelperCallback(itemsAdapter));
itemTouchHelper.attachToRecyclerView(r);
});
}
public interface ItemTouchHelperAdapter {
void onItemMoved(int fromPosition, int toPosition);
void onItemDropped(int position); // Optional for handling dropped items on image
}
public class skutest_recyclerview_viewadapter extends RecyclerView.Adapter<skutest_recyclerview_viewadapter.ViewHolder> implements ItemTouchHelperAdapter
{
RecyclerView mRecyclerView;
List<cl_sku_info> skulist;
public skutest_recyclerview_viewadapter(List<cl_sku_info> skulist)
{
this.skulist=skulist;
}
@NonNull
@Override
public skutest_recyclerview_viewadapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
ItemBinding b = ItemBinding.inflate(inflater, parent, false);
return new ViewHolder(b);
}
@Override
public void onBindViewHolder(@NonNull skutest_recyclerview_viewadapter.ViewHolder holder, int position)
{
holder.setData(skulist.get(position));
}
@Override
public int getItemCount()
{
return skulist==null ? 0 : skulist.size();
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView)
{
super.onAttachedToRecyclerView(recyclerView);
mRecyclerView = recyclerView;
}
@Override
public void onItemMoved(int fromPosition, int toPosition)
{
}
@Override
public void onItemDropped(int position)
{
}
public static class ViewHolder extends RecyclerView.ViewHolder
{
private final ItemBinding binding;
public ViewHolder(ItemBinding binding)
{
super(binding.getRoot());
this.binding=binding;
}
public void setData(cl_sku_info clSkuInfo)
{
binding.label.setText("*****");//clSkuInfo.getSTOCK_NO());
binding.image.setImageBitmap(images.getInstance().getimage(clSkuInfo.getSTOCK_NO(),100));
}
}
}
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
public class ItemTouchHelperCallback extends ItemTouchHelper.Callback
{
private final ItemTouchHelperAdapter adapter;
public ItemTouchHelperCallback(ItemTouchHelperAdapter adapter)
{
this.adapter = adapter;
}
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder)
{
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.RIGHT | ItemTouchHelper.LEFT;
final int swipeFlags = 0; // Disable swiping for now
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target)
{
adapter.onItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction)
{
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="2"
android:hardwareAccelerated="false"
tools:context=".activities.MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/myrecyclerview"
android:layout_width="0dp"
android:layout_height="match_parent"
tools:itemCount="20"
android:layout_weight="1"
tools:listitem="@layout/item" />
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/i1"
android:scaleType="center" />
</LinearLayout>
As you can see in the images the dragged item is getting lost underneath the target image. I thought that the default behaviour was to float above everything and I can't see where I've gone wrong.
It turns out i had taken the wrong approach.
The issue is resolved by discarding the
ItemTouchHelperCallback and ItemTouchHelperAdapter
getting rid of
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemTouchHelperCallback(itemsAdapter));
itemTouchHelper.attachToRecyclerView(r);
changing
@SuppressLint("ClickableViewAccessibility")
@Override
public void onBindViewHolder(@NonNull skutest_recyclerview_viewadapter.ViewHolder holder, int position)
{
holder.setData(skulist.get(position));
holder.getBinding().getRoot().setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
return tevent(v,event);
}
});
//holder.getBinding().getRoot().setOnDragListener(new DragListener());
}
and adding below (credits https://github.com/jkozh/DragDropTwoRecyclerViews)
public boolean tevent(View v,MotionEvent event)
{
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
ClipData data = ClipData.newPlainText("", "");
View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(v);
v.startDragAndDrop(data, shadowBuilder, v, 0);
v.performClick();
return true;
}
return false;
}
There was a large amount of quagmire to get to this understanding. The default drag and drop functionality of the recyclerview appears to be intended for operations withing the same recyclerview such as re-ordering. When you want the drag to escape the recyclerview and float over everything you have to do something like this.