I am using 2 RecyclerViews inside a Dialogue. One of the RecyclerView further uses a nested list inside it. Everything's alright till now (no height issues).
However, from the other RecyclerView, I drag an image/view and inside another RecyclerView i wish to drop it.
This functionality works fine but problem occurs here:
I usually highlight a particular Text area when the dragged image enters that area using DragListener's available Drag events (see image below):
So if I drag the image till "Customer Voice 5" Text header, it'll highlight.
When I drag it to the 5th item, it scrolls down (as coded inside DragListener using smoothScrollBy()
) and 6th item with the header "Customer Voice 6" Text header is also visible, BUT it doesn't get highlighted. Neither it scrolls down further to show 7th completely, no code works on this item, as if RecyclerView hasn't yet updated/recognized this item inside it's onBindViewHolder(...) method.
Now I drop the dragged image elsewhere (no action) and again drag image to "Customer Header 6", it highlights! (and scrolls too) That means RecyclerView has updated it after I had dropped my image on the first run.
So while I drag, the Drag Listener's event ACTION_DRAG_LOCATION runs continuously and Recycler View seems to not able to take the control while this happens. So how to get both things DragListener and RecyclerViewAdapter, work together? [I am aware how RV uses the items from holder and re-uses it when invisible from to dirty view list]
I tried notifyDataSetChanged(); but doesn't help. Can't find any other thing on this. Maybe LinearLayoutManager might help but can't link it with my problem. Below are some code blocks from my RV adapter.
@Override
public void onBindViewHolder(MyHolder holder, int position) {
Log.d("Log","OnBindViewHolder"+position);
holder.customerVoiceTitle.setText(hashMap.get(position)); //Setting Header Text - "Customer Voice [position+1]"
holder.customerVoiceTitle.setId(position + 100); // Setting id to be able to detect each header while performing drag actions
holder.customerVoiceTitle.setOnDragListener(new MyDragListener());
customerVoiceMainHeaderText.setId(50); //Neglect this for the time being, this is also a part of the issue.
customerVoiceMainHeaderText.setOnDragListener(new MyDragListener());
holder.totalWorkLayoutListView.setId(position + 150); //ListView also is utilized to perform drag actions
holder.totalWorkLayoutListView.setOnDragListener(new MyDragListener());
UtilityClass.setListViewHeightBasedOnChildren(holder.totalWorkLayoutListView, "", ""); //To avoid height inflation issues
/* if(allFlag) {
customerVoiceWorkListCustomAdapter = new CustomerVoiceWorkListCustomAdapter(context, 5, true);
}
else if(!allFlag) {
customerVoiceWorkListCustomAdapter = new CustomerVoiceWorkListCustomAdapter(context, 5, false);
}*/
holder.totalWorkLayoutListView.setAdapter(customerVoiceWorkListCustomAdapter);
}
class MyDragListener implements View.OnDragListener {
Drawable normalShape = context.getResources().getDrawable(R.drawable.bg_fragment_header_with_border);
Drawable targetShape = context.getResources().getDrawable(R.drawable.target_shape);
@Override
public boolean onDrag(View v, DragEvent event) {
// Handles each of the expected events
switch (event.getAction()) {
//signal for the start of a drag and drop operation.
case DragEvent.ACTION_DRAG_STARTED:
// do nothing
break;
//the drag point has entered the bounding box of the View
case DragEvent.ACTION_DRAG_ENTERED:
if(v.getId() >= 100 && v.getId() < 150) //For Header Text only
v.setBackground(targetShape); //change the shape of the view
break;
//the user has moved the drag shadow outside the bounding box of the View
case DragEvent.ACTION_DRAG_EXITED:
if(v.getId() >= 100 && v.getId() < 150) //For Header Text only
v.setBackground(normalShape); //change the shape of the view back to normal
break;
//drag shadow has been released,the drag point is within the bounding box of the View
case DragEvent.ACTION_DROP:
Log.d("Log", "" + v.getId());
// if the view is the bottomlinear, we accept the drag item
if (v.getId() >= 100 && v.getId() < 150) { //For Header Text only. If dragged image is dropped some changes take place inside the list. Not IMP now
TextView workListHeaderText = (TextView) v;
LinearLayout containerLayout = (LinearLayout) workListHeaderText.getParent();
ListView workLayoutList = (ListView) containerLayout.getChildAt(1);
customerVoiceWorkListCustomAdapter = new CustomerVoiceWorkListCustomAdapter(context, 5, true);
workLayoutList.setAdapter(customerVoiceWorkListCustomAdapter);
} else if (v.getId() == 50) {
allFlag = true;
TextView workListRootHeaderText = (TextView) v;
LinearLayout layout = (LinearLayout) workListRootHeaderText.getParent();
RecyclerView technicianAllotment = (RecyclerView) layout.getChildAt(1);
int childCount = technicianAllotment.getChildCount();
for (int listCount = 0; listCount < childCount; listCount++) {
LinearLayout linearLayout = (LinearLayout) technicianAllotment.getChildAt(listCount);
ListView workLayoutList = (ListView) linearLayout.getChildAt(1);
customerVoiceWorkListCustomAdapter = new CustomerVoiceWorkListCustomAdapter(context, 5, true);
workLayoutList.setAdapter(customerVoiceWorkListCustomAdapter);
UtilityClass.setListViewHeightBasedOnChildren(workLayoutList, "", "");
}
}
break;
case DragEvent.ACTION_DRAG_LOCATION: //This is used to scroll when dragged image is dragged to the bottom of screen
LinearLayout dropZoneView = (LinearLayout) v.getParent();
int topOfDropZone = dropZoneView.getTop();
int bottomOfDropZone = dropZoneView.getBottom();
int scrollY = recyclerView.getScrollY();
int scrollViewHeight = recyclerView.getMeasuredHeight();
Log.d("Log", "location: Scroll Y: " + scrollY + " Scroll Y+Height: " + (scrollY + scrollViewHeight));
Log.d("Log", " top: " + topOfDropZone + " bottom: " + bottomOfDropZone);
if (bottomOfDropZone > (scrollY + scrollViewHeight - 100)) { //Manual scrolling down when image is dragged to bottom RV item
notifyDataSetChanged();
recyclerView.smoothScrollBy(0, 300);
}
if (topOfDropZone < (scrollY + 50)) //Manual scrolling up
recyclerView.smoothScrollBy(0, -50);
break;
//the drag and drop operation has concluded.
case DragEvent.ACTION_DRAG_ENDED:
if(v.getId() >= 100 && v.getId() < 150)
v.setBackground(normalShape); //go back to normal shape
default:
break;
}
return true;
}
}
EDIT
https://stackoverflow.com/a/14458111/4452231
This so far has worked. Got better solutions? Kindly suggest.