Alex Newton
Alex Newton

Reputation: 163

Android OnDragListener - ACTION_DRAG_ENDED firing multiple times

I'm making a list view with custom rows and custom Adapter. I've attached an OnTouchListener and OnDragListener to each view in the list view.

I'm updating the underlying data if the drop result is true (the view being dragged is dropped within the bounds of the list view)

The ACTION_DRAG_ENDED case fires 4 times for both valid and invalid drops but I don't know why. Can someone please tell me why this is happening?

My code for the listeners is below.

@Override
        public View getView(final int position, View convertView, final ViewGroup parent) {

            LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
            if (convertView == null) {
                convertView = inflater.inflate(R.layout.lv_item_stage, parent, false);
            }

            //setting text/images for the view

            convertView.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View view, MotionEvent motionEvent) {
                    if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                        START_POS = position;

                        ClipData data = ClipData.newPlainText("", "");
                        View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
                        view.startDrag(data, shadowBuilder, view, 0);
                        view.setVisibility(View.GONE);
                        return true;
                    } else {
                        return false;
                    }
                }
            });

            convertView.setOnDragListener(new View.OnDragListener() {
                @Override
                public boolean onDrag(final View v, DragEvent event) {
                    switch (event.getAction()) {
                        case DragEvent.ACTION_DRAG_ENTERED:
                            AbsListView.LayoutParams params = new AbsListView.LayoutParams(v.getWidth(), v.getHeight()*2);

                            if(position > START_POS){
                                //view dragged downwards
                                moveData(START_POS, position);
                                ((LinearLayout) v).setGravity(Gravity.TOP);
                            }
                            else{
                                //view dragged upwards
                                moveData(START_POS, position);
                                ((LinearLayout ) v).setGravity(Gravity.BOTTOM);
                            }

                            v.setLayoutParams(params);

                            START_POS = position;
                            break;

                        case DragEvent.ACTION_DRAG_EXITED:
                            //go straight into ACTION_DROP case (resize view to original size)
                        case DragEvent.ACTION_DROP:
                            v.setLayoutParams(new AbsListView.LayoutParams(v.getWidth(), v.getHeight()/2));
                            break;
                        case DragEvent.ACTION_DRAG_ENDED:
                            //update list view if drop valid (inside list view)
                            if (event.getResult()){
                                Log.d("listView", "result = TRUE");
                                updateListView(tempData);
                            }
                            else{
                                Log.d("listView", "result = FALSE");
                            }

                            final View droppedView = (View) event.getLocalState();
                            droppedView.post(new Runnable() {
                                @Override
                                public void run() {
                                    droppedView.setVisibility(View.VISIBLE);
                                }
                            });
                            break;
                        default:
                            break;
                    }
                    return true;
                }
            });
            return convertView;
        }

Upvotes: 2

Views: 1189

Answers (2)

Mahmut K.
Mahmut K.

Reputation: 850

private bool wasShown;

Do false in the ontouch event.

wasShown = false;

Check with if and set it to true the first time it runs in ACTION_DRAG_ENDED.

if (!wasShown){
wasShown = true;
...
}

Upvotes: 0

Adam G
Adam G

Reputation: 11

ACTION_DRAG_ENDED will fire one time for each view that you have attached the drag listener to. The same is true for ACTION_DRAG_STARTED. Therefore, if you attached the onDragListener to 4 views, these events will fire 4 times.

Upvotes: 1

Related Questions