Lendl Leyba
Lendl Leyba

Reputation: 2287

Android GridView Custom Drag and Drop

I have a gridview that I need to implement drag and drop feature. I've been trying to find a possible solution or existing library that would fit my problem but still no luck.

Here's a before and after illustration of the drag and drop that I need to implement:

enter image description here

The red tiles are items wherein they cannot be dragged nor dropped on. the blue ones are draggable and can be dropped on any tile on any row, just not on the red tiles. The white tiles are just placeholders which are placed to have the red tiles on the first column.

Now, when tile A is dragged on the 3rd row, as you can see, they go side by side, not swapped, even if put on top of tile C. The number of white tiles is depending on the number of blue tiles per row, an arraylist is assigned on each row, so it'll just follow. My real problem is that all examples on gridview drag and drop is that tiles swaps or the whole grid follows the flow of items.

My plan to implement this:

  1. When long pressed on a tile to be dragged, it will show a tile that looks like that tile, only larger and lesser opacity.
  2. When dropped on a certain position, will compute for the row.
  3. Adjust arraylists and notifydatasetchanged.

Here's breaking down the problem to slightly smaller problems:

  1. How can I make a larger tile of the long pressed tile?
  2. Is it possible to get the position where the enlarged tile is dropped?

Upvotes: 0

Views: 1404

Answers (3)

Lendl Leyba
Lendl Leyba

Reputation: 2287

I ended up editting http://code.google.com/p/android-gridview-drag-and-drop/ to fit my problem.

Upvotes: 0

theodore
theodore

Reputation: 47

1.How can I make a larger tile of the long pressed tile? yes,you can get the tile's view and create a new bitmap,the add the bitmap to Windows.Like this : it's a class extends GridView.

public boolean setOnItemLongClickListener(final MotionEvent ev)
{
    this.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener()
    {
        @Override
        public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
                int arg2, long arg3)
        {
            // onInterceptTouchEvent(ev);
            // TODO Auto-generated method stub
            L.l("============on Long Click=========");
            L.l("============X:" + ev.getX() + " Y:" + ev.getY());

            int x = (int) ev.getX();
            int y = (int) ev.getY();
            dragPosition = dropPosition = pointToPosition(x, y);
            System.out.println(dragPosition);
            if (dragPosition == AdapterView.INVALID_POSITION)
            {

            }
            ViewGroup itemView = (ViewGroup) getChildAt(dragPosition
                    - getFirstVisiblePosition());

            dragPointX = x - itemView.getLeft();
            dragPointY = y - itemView.getTop();

            dragOffsetX = (int) (ev.getRawX() - x);
            dragOffsetY = (int) (ev.getRawY() - y);

            itemHeight=itemView.getHeight();

            L.l("========================y:" + y + " getRawY:"
                    + ev.getRawY());


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

            startDrag(bm, x, y);
            return false;
        };
    });
    return super.onInterceptTouchEvent(ev);
}

    private void startDrag(Bitmap bm, int x, int y)
{

    windowParams = new WindowManager.LayoutParams();
    windowParams.gravity = Gravity.TOP | Gravity.LEFT;// 这个必须加
    windowParams.x = x - dragPointX + dragOffsetX;
    windowParams.y = y - dragPointY + dragOffsetY;

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

    windowParams.format = PixelFormat.TRANSLUCENT;
    windowParams.windowAnimations = 0;

    ImageView iv = new ImageView(getContext());
    iv.setImageBitmap(bm);
    windowManager = (WindowManager) getContext().getSystemService(
            Context.WINDOW_SERVICE);// "window"
    windowManager.addView(iv, windowParams);
    dragImageView = iv;
}


    @Override
public boolean onTouchEvent(MotionEvent ev)
{
    if (dragImageView != null
            && dragPosition != AdapterView.INVALID_POSITION)
    {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        switch (ev.getAction())
        {
            case MotionEvent.ACTION_MOVE:
                onDrag(x, y);
                break;
            case MotionEvent.ACTION_UP:
                stopDrag();
                onDrop(x, y);
                break;
        }
    }
    return super.onTouchEvent(ev);
}

private void onDrag(int x, int y)
{
    if (dragImageView != null)
    {
        windowParams.alpha = 0.6f;
        windowParams.x = x - dragPointX + dragOffsetX;
        windowParams.y = y - dragPointY + dragOffsetY;
        // L.l("=================windowParams.y=====000========"+windowParams.y);
        windowManager.updateViewLayout(dragImageView, windowParams);
    }

    int tempScrollX = x - dragPointX + dragOffsetX;
    int tempScrollY = y - dragPointY + dragOffsetY;

    if (tempScrollY +itemHeight> 600)
    {
        this.scrollTo(0, tempScrollY);
    }
    else
        if (pointToPosition(x, y) > 2)
        {

            this.scrollTo(0, tempScrollY - 300);
        }

}

2.Is it possible to get the position where the enlarged tile is dropped? If your class is extends GridView or AbsListView,this API `pointToPosition(x, y) will return the position of the whole view.

Upvotes: 3

theodore
theodore

Reputation: 47

When you drop tile A,then you calculate where tile A is now,if above tile C,then start a Animation(C move to side and A take place position of C) and update the Adapter end of the Animation.

Upvotes: 0

Related Questions