Drag and Drop in GridView in Android

10,281

Solution 1

see PagedDragDropGrid

Above example has implemented a paged grid with drag'n'drop movable items using ViewGroup.

Note@ It supports Android 2.2 (API 8) and above.

Solution 2

This is finest example i ever seen in android drag and drop android 2.2. And which version you have used?

Solution 3

Try another approach by using WindowManager :

    package com.example.cooldraganddrop;

    import android.content.Context;
    import android.graphics.Bitmap;
    import android.graphics.Color;
    import android.graphics.PixelFormat;
    import android.graphics.drawable.BitmapDrawable;

    import android.util.AttributeSet;
    import android.view.Gravity;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.WindowManager;
    import android.widget.AdapterView;
    import android.widget.ImageView;

    public class CoolDragAndDropGridView extends SpanVariableGridView implements `View.OnTouchListener {`

        private static final int ITEM_HOVER_DELAY = 450;

        private int mDragPointX;
        private int mDragPointY;
        private int mDragOffsetX;
        private int mDragOffsetY;
        private int mDragPosition = AdapterView.INVALID_POSITION;
        private int mDropPosition = AdapterView.INVALID_POSITION;
        private int mCurrentPosition = AdapterView.INVALID_POSITION;
        private Runnable mDelayedOnDragRunnable = null;

        ScrollingStrategy mScrollingStrategy = null;
        WindowManager mWindowManager = null;
        WindowManager.LayoutParams mWindowParams = null;
        private ImageView mDragImageView = null;
        private boolean mDragAndDropStarted = false;
        private DragAndDropListener mDragAndDropListener = null;
        private OnTrackTouchEventsListener mOnTrackTouchEventsListener = null;

        public static interface OnTrackTouchEventsListener {

                void trackTouchEvents(final MotionEvent motionEvent);

        };

        public static interface DragAndDropListener {

                void onDragItem(int from);

                void onDraggingItem(int from, int to);

                void onDropItem(int from, int to);

                boolean isDragAndDropEnabled(int position);
        }

        public CoolDragAndDropGridView(Context context) {
                super(context);

                initialize();
        }

        public CoolDragAndDropGridView(Context context, AttributeSet attrs, int defStyle) {
                super(context, attrs, defStyle);

                initialize();
        }

        public CoolDragAndDropGridView(Context context, AttributeSet attrs) {
                super(context, attrs);

                initialize();
        }

        private void initialize() {
                setOnTouchListener(this);
                setChildrenDrawingOrderEnabled(true);
        }

        public void startDragAndDrop() {

                mDragAndDropStarted = true;

        }

        public void setDragAndDropListener(DragAndDropListener dragAndDropListener) {

                mDragAndDropListener = dragAndDropListener;

        }

        private void destroyDragImageView() {

                if (mDragImageView != null) {

                        mWindowManager.removeView(mDragImageView);

                        BitmapDrawable bitmapDrawable = (BitmapDrawable) mDragImageView.getDrawable();
                        if (bitmapDrawable != null) {
                                final Bitmap bitmap = bitmapDrawable.getBitmap();
                                if (bitmap != null && !bitmap.isRecycled()) {
                                        bitmap.recycle();
                                }
                        }

                        mDragImageView.setImageDrawable(null);
                        mDragImageView = null;
                }

        }

        private ImageView createDragImageView(final View v, final int x, final int y) {

                v.destroyDrawingCache();
                v.setDrawingCacheEnabled(true);
                Bitmap bm = Bitmap.createBitmap(v.getDrawingCache());

                mDragPointX = x - v.getLeft();
                mDragPointY = y - v.getTop();

                mWindowParams = new WindowManager.LayoutParams();
                mWindowParams.gravity = Gravity.TOP | Gravity.LEFT;

                mWindowParams.x = x - mDragPointX + mDragOffsetX;
                mWindowParams.y = y - mDragPointY + mDragOffsetY;

                mWindowParams.height = WindowManager.LayoutParams.WRAP_CONTENT;
                mWindowParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
                mWindowParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
                                | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;

                mWindowParams.format = PixelFormat.TRANSLUCENT;
                mWindowParams.alpha = 0.7f;
                mWindowParams.windowAnimations = 0;

                ImageView iv = new ImageView(getContext());
                iv.setBackgroundColor(Color.parseColor("#ff555555"));
                iv.setImageBitmap(bm);

                mWindowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);// "window"
                mWindowManager.addView(iv, mWindowParams);
                return iv;

        }

        private void startDrag(final int x, final int y) {

                final View v = getChildAt(mDragPosition);

                destroyDragImageView();

                mDragImageView = createDragImageView(v, x, y);
                v.setVisibility(View.INVISIBLE);

                if (mDragAndDropListener != null) {

                        mDragAndDropListener.onDragItem(mDragPosition);
                }

        }

        @Override
        protected int getChildDrawingOrder(int childCount, int i) {
                if (mCurrentPosition == -1)
                        return i;
                else if (i == childCount - 1)
                        return mCurrentPosition;
                else if (i >= mCurrentPosition)
                        return i + 1;
                return i;
        }

        private void onDrop() {

                destroyDragImageView();

                removeCallbacks(mDelayedOnDragRunnable);

                View v = getChildAt(mDropPosition);
                v.setVisibility(View.VISIBLE);

                v.clearAnimation();

                if (mDragAndDropListener != null && mDropPosition != AdapterView.INVALID_POSITION) {

                        mDragAndDropListener.onDropItem(mDragPosition, mDropPosition);
                }

                mDragPosition = mDropPosition = mCurrentPosition = AdapterView.INVALID_POSITION;
                mDragAndDropStarted = false;
        }

        public void setScrollingStrategy(ScrollingStrategy scrollingStrategy) {

                mScrollingStrategy = scrollingStrategy;

        }

        private void onDrag(final int x, final int y) {

                if (mScrollingStrategy != null && mScrollingStrategy.performScrolling(x, y, this)) {

                        removeCallbacks(mDelayedOnDragRunnable);

                        return;
                }

                final int tempDropPosition = pointToPosition(mCurrentPosition, x, y);

                if (mDragAndDropListener != null && mDropPosition != tempDropPosition && tempDropPosition != AdapterView.INVALID_POSITION) {

                        removeCallbacks(mDelayedOnDragRunnable);

                        if (mDragAndDropListener.isDragAndDropEnabled(tempDropPosition)) {

                                mDropPosition = tempDropPosition;

                                mDelayedOnDragRunnable = new Runnable() {

                                        @Override
                                        public void run() {

                                                mDragAndDropListener.onDraggingItem(mCurrentPosition, tempDropPosition);
                                                performDragAndDropSwapping(mCurrentPosition, tempDropPosition);

                                                final int nextDropPosition = pointToPosition(tempDropPosition, x, y);

                                                if (nextDropPosition == AdapterView.INVALID_POSITION) {

                                                        mCurrentPosition = mDropPosition = tempDropPosition;

                                                }
                                        }
                                };

                                postDelayed(mDelayedOnDragRunnable, ITEM_HOVER_DELAY);

                        } else {

                                mDropPosition = mDragPosition;

                        }

                }

                if (mDragImageView != null) {

                        mWindowParams.x = x - mDragPointX + mDragOffsetX;
                        mWindowParams.y = y - mDragPointY + mDragOffsetY;
                        mWindowManager.updateViewLayout(mDragImageView, mWindowParams);
                }

        }

        public void setOnTrackTouchEventListener(OnTrackTouchEventsListener onTrackTouchEventsListener) {

                mOnTrackTouchEventsListener = onTrackTouchEventsListener;
        }

        @Override
        public boolean onInterceptTouchEvent(MotionEvent event) {

                if (mOnTrackTouchEventsListener != null) {
                        mOnTrackTouchEventsListener.trackTouchEvents(event);
                }

                switch (event.getAction()) {

                case MotionEvent.ACTION_DOWN:
                case MotionEvent.ACTION_MOVE:

                        if (mDragAndDropListener != null && mDragAndDropStarted) {

                                mDragAndDropStarted = false;

                                getParent().requestDisallowInterceptTouchEvent(true);

                                return launchDragAndDrop(event);
                        }

                        break;

                default:
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:

                        mDragAndDropStarted = false;

                        getParent().requestDisallowInterceptTouchEvent(false);

                        break;
                }

                return super.onInterceptTouchEvent(event);
        }

        private boolean launchDragAndDrop(final MotionEvent event) {

                final int x = (int) event.getX();
                final int y = (int) event.getY();

                mCurrentPosition = mDragPosition = mDropPosition = pointToPosition(mDragPosition, x, y);

                if (mDragPosition != AdapterView.INVALID_POSITION && mDragAndDropListener.isDragAndDropEnabled(mDragPosition)) {

                        mDragOffsetX = (int) (event.getRawX() - x);
                        mDragOffsetY = (int) (event.getRawY() - y);

                        startDrag(x, y);

                        return true;
                }

                return false;
        }

        @Override
        public boolean onTouch(View view, MotionEvent event) {

                if (mDragPosition != AdapterView.INVALID_POSITION && mDragImageView != null) {

                        final int x = (int) event.getX();
                        final int y = (int) event.getY();

                        switch (event.getAction()) {

                        case MotionEvent.ACTION_MOVE:

                                mDragOffsetX = (int) (event.getRawX() - x);
                                mDragOffsetY = (int) (event.getRawY() - y);

                                onDrag(x, y);

                                break;

                        case MotionEvent.ACTION_UP:
                        case MotionEvent.ACTION_CANCEL:

                                onDrop();

                                resetLongClickTransition();

                                getParent().requestDisallowInterceptTouchEvent(false);

                                return false;

                        default:

                        }

                        return true;
                }

                return false;
        }
}

Sample using this approach of a drag and drop is here

Solution 4

You can find the google's documentation on drag and drop here and a third parties example here.

What you're going to want to do is set every view in your gridView to be clickable and set the onTouchListener. In your onTouch method you would then handle the appropriate actions for ACTION_DOWN (user pressed down on screen), ACTION_MOVE (user moves finger around ont he screen) and ACTION_UP (user lifts finger from the screen).

Share:
10,281

Related videos on Youtube

Gaurav Arora
Author by

Gaurav Arora

I am a passionate Android Developer.

Updated on September 15, 2022

Comments

  • Gaurav Arora
    Gaurav Arora over 1 year

    How can a drag and drop functionality be implemented in Android GridView. Can anyone please provide the best link for the same?

  • Gaurav Arora
    Gaurav Arora over 11 years
    I have to make it for Android 2.2.
  • Hardik Joshi
    Hardik Joshi over 11 years
    Then use example which i give you.
  • Gaurav Arora
    Gaurav Arora over 11 years
    Ok Thanks let me check the same.
  • Gaurav Arora
    Gaurav Arora over 11 years
    Hardik , I think that this is not for the GridView ?
  • Hardik Joshi
    Hardik Joshi over 11 years
  • Gaurav Arora
    Gaurav Arora over 11 years
    Yeah! this one is fine. Can you help me in one thing that I want to show only 9 items in gridview on one page, I want that rest of them comes on next page, is this possible?
  • Hardik Joshi
    Hardik Joshi over 11 years
    Sorry Gaurav in this time no idea dude. TIme to leave and thanks for your compliments.
  • Gaurav Arora
    Gaurav Arora over 11 years
    No bro :( My case is very much typical. Me not able to get all the things. Can I have ur gmail id ?
  • Hardik Joshi
    Hardik Joshi over 11 years
  • zabawaba99
    zabawaba99 over 11 years
    If you still need help solving it, let me know. I believe I have a pretty good idea in how to help you out.
  • Gaurav Arora
    Gaurav Arora over 11 years
    Please help me zabawaba. I am still solving it and I am not able make any progress yet now?? :( :(