DragAndDropSort icon indicating copy to clipboard operation
DragAndDropSort copied to clipboard

Error when using on Android platform ver 6.0 or 5.1

Open phamthanhtong opened this issue 7 years ago • 9 comments

I tested on Android 7.0 is OK. But when the app builded on Android devices either Android 6.0 Marshmallow or Android 5.1 Lollipop

When drag viewcell in listview, I got an error "Specified cast is not valid." At method: public bool OnDrag(AViews.View v, DragEvent e) var dragItem = (DragItem)e.LocalState;

Could you share me how to fix it?

phamthanhtong avatar Jan 08 '19 10:01 phamthanhtong

Here the same, I can fix this:

case DragAction.Entered:
    if (Build.VERSION.SdkInt >= BuildVersionCodes.N) {
        ...
    } else {
        var id = (int) e.LocalState;
        var selectedItem = ((IList) _element.ItemsSource)[id];
        dragItem = new DragItem(NormalizeListPosition(id + 1), v, selectedItem);
    }
    ...

But the problem is case DragAction.Ended: Any suggestion, how can I fix this in Android 5.1/6.0?

tualatin avatar Feb 20 '19 08:02 tualatin

Thank you very much for answering my prayer, Jesus

Working fix for Android 5.1 is here (must work on Android 6 also) :

Change 1

public bool OnItemLongClick(AWidget.AdapterView parent, AViews.View view, int position, long id)
       {
           var selectedItem = ((IList)_element.ItemsSource)[(int)id];

           DragItem dragItem = new DragItem(NormalizeListPosition(position), view, selectedItem);

           var data = ClipData.NewPlainText(string.Empty, string.Empty);

           AViews.View.DragShadowBuilder shadowBuilder = new AViews.View.DragShadowBuilder(view);

           view.Visibility = ViewStates.Invisible;

           if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
           {
               view.StartDragAndDrop(data, shadowBuilder, dragItem, 0);
           }
           else
           {
               // UPDATE-1 : send dragItem as parameter here
               view.StartDrag(data, shadowBuilder, dragItem, 0);
           }

           return true;
       }

and the other part to be changed

// UPDATE-2 : Move the operations from DragAction.Ended to DragAction.Drop
case DragAction.Drop:
                    System.Diagnostics.Debug.WriteLine($"DragAction.Drop from {v.GetType()}");
                    if (!(v is AWidget.ListView))
                    {
                        return false;
                    }

                    var mobileItem = (DragItem)e.LocalState;

                    mobileItem.View.Visibility = ViewStates.Visible;

                    foreach (var view in _translatedItems)
                    {
                        view.TranslationY = 0;
                    }

                    _translatedItems.Clear();

                    // I used index-1 below for solving inconsistency as Lists/IObservable has zero based index 
                   //in our manipulation, I kept the CHangeOrdinal method in this file itself without IOrderable interface
                    ChangeOrdinal(mobileItem.OriginalIndex - 1, mobileItem.Index - 1);
                    break;

 case DragAction.Ended:
                    System.Diagnostics.Debug.WriteLine($"DragAction.Ended from {v.GetType()}");
                   break;

The problem finally was that we were not getting the view 'v' as Listview at DragAction.Ended for Android 5.1 alone (hopefully also for Android 6), but we got 'v' as AWidget.ListView at DragAction.Drop

@canbilgin has initially had it in DragAction.Drop only, as posted in the blog

Hope you got it fixed!

For Reference,

public bool OnDrag(AViews.View v, DragEvent e)
{
     switch (e.Action)
        {
            case DragAction.Started:
                    break;
            case DragAction.Entered:
                    System.Diagnostics.Debug.WriteLine($"DragAction.Entered from {v.GetType()}");

                    if (!(v is AWidget.ListView))
                    {
                        var dragItem = (DragItem)e.LocalState;

                        _dragItem = dragItem;

                        var targetPosition = InsertOntoView(v, dragItem);

                        dragItem.Index = targetPosition;

                        // Keep a list of items that has translation so we can reset
                        // them once the drag'n'drop is finished.
                        _translatedItems.Add(v);
                        _listView.Invalidate();
                    }
                    break;
            case DragAction.Location:
                    break;
            case DragAction.Exited:
                    System.Diagnostics.Debug.WriteLine($"DragAction.Exited from {v.GetType()}");
                    break;
                case DragAction.Drop:
                    System.Diagnostics.Debug.WriteLine($"DragAction.Drop from {v.GetType()}");
                    if (!(v is AWidget.ListView))
                    {
                        return false;
                    }

                    var mobileItem = (DragItem)e.LocalState;

                    mobileItem.View.Visibility = ViewStates.Visible;

                    foreach (var view in _translatedItems)
                    {
                        view.TranslationY = 0;
                    }

                    _translatedItems.Clear();

                    ChangeOrdinal(mobileItem.OriginalIndex - 1, mobileItem.Index - 1);
                    break;
            case DragAction.Ended:
                    System.Diagnostics.Debug.WriteLine($"DragAction.Ended from {v.GetType()}");

                    break;
            }

            return true;
        }

PaulsonM avatar Feb 26 '19 14:02 PaulsonM

@PaulsonMac thank you very much, your solution works like a charm! Nice job.

tualatin avatar Feb 27 '19 14:02 tualatin

I have another question, how can I handle invalid Drag'n'Drop? When user drops the item outside the listview, it will disappear. Any suggestions?

tualatin avatar Mar 06 '19 14:03 tualatin

@phamthanhtong, @tualatin, did you get the issue #2 I opened?

PaulsonM avatar Apr 04 '19 07:04 PaulsonM

Hi @canbilgin, this issue is closed. But still the code needs to be committed to your repository right?

PaulsonM avatar May 17 '19 13:05 PaulsonM

guys why dont you create a pr.. or should I push the code changes?

canbilgin avatar May 29 '19 03:05 canbilgin

Hi @canbilgin, this issue is closed. But still the code needs to be committed to your repository right?

thanks alot to your fixed

Chitsoehein avatar Oct 12 '21 17:10 Chitsoehein

**thanks to your success codes for v 6.0 **

Chitsoehein avatar Oct 31 '21 08:10 Chitsoehein