package com.mehtank.androminion.ui; import android.content.Context; import android.graphics.Bitmap; import android.graphics.PixelFormat; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.ImageView; import android.widget.ListView; public class DragNDropListView extends ListView { @SuppressWarnings("unused") private static final String TAG = "DragNDropListView"; boolean mDragMode; int mStartPosition; int mCurrentPosition; int mEndPosition; int mDragPointYOffset; //Used to adjust drag view location int mDragPointXOffset; //Used to adjust drag view location int mOrigX; ImageView mDragView; View mHiddenView; GestureDetector mGestureDetector; DragListener mDragListener; public DragNDropListView(Context context) { super(context); } public DragNDropListView(Context context, AttributeSet attrs) { super(context, attrs); } public void setDropListener(DragListener l) { mDragListener = l; } @Override public boolean onTouchEvent(MotionEvent ev) { final int action = ev.getAction(); final int x = (int) ev.getX(); final int y = (int) ev.getY(); if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_MOVE) { mDragMode = true; } if (!mDragMode) return super.onTouchEvent(ev); switch (action) { /* default: if (mDragView != null) drag(x,y); break; */ case MotionEvent.ACTION_MOVE: if (mDragView != null) { drag(x,y); break; } case MotionEvent.ACTION_DOWN: mStartPosition = pointToPosition(x,y); if (mStartPosition != INVALID_POSITION) { mOrigX = x; int mItemPosition = mStartPosition - getFirstVisiblePosition(); mDragPointYOffset = y - getChildAt(mItemPosition).getTop(); mDragPointYOffset -= ((int)ev.getRawY()) - y; mDragPointXOffset = x - getChildAt(mItemPosition).getLeft(); mDragPointXOffset -= ((int)ev.getRawX()) - x; startDrag(mItemPosition,y); mCurrentPosition = mItemPosition; drag(x,y); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: notifyDrag(x, y); stopDrag(); mDragMode = false; break; default: if (mDragView != null) drag(x, y); break; } return true; } private void notifyDrag(int x, int y) { mEndPosition = pointToPosition(mOrigX, y); if (mHiddenView != null) mHiddenView.setVisibility(VISIBLE); mHiddenView = getChildAt(mCurrentPosition); if (mHiddenView != null) mHiddenView.setVisibility(INVISIBLE); if (mCurrentPosition == mEndPosition) return; if (mDragListener != null && mCurrentPosition != INVALID_POSITION && mEndPosition != INVALID_POSITION) { if (mHiddenView != null) mHiddenView.setVisibility(VISIBLE); mDragListener.onDrag(mCurrentPosition, mEndPosition); mCurrentPosition = mEndPosition; } } // move the drag view private void drag(int x, int y) { WindowManager.LayoutParams layoutParams = (WindowManager.LayoutParams)mDragView.getLayoutParams(); layoutParams.x = x - mDragPointXOffset; layoutParams.y = y - mDragPointYOffset; WindowManager mWindowManager = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE); mWindowManager.updateViewLayout(mDragView, layoutParams); notifyDrag(x, y); } // enable the drag view for dragging private void startDrag(int itemIndex, int y) { stopDrag(); requestDisallowInterceptTouchEvent(true); View item = getChildAt(itemIndex); if (item == null) return; item.setDrawingCacheEnabled(true); // Create a copy of the drawing cache so that it does not get recycled // by the framework when the list tries to clean up memory Bitmap bitmap = Bitmap.createBitmap(item.getDrawingCache()); WindowManager.LayoutParams mWindowParams = new WindowManager.LayoutParams(); mWindowParams.gravity = Gravity.TOP; mWindowParams.x = 0 - mDragPointXOffset; mWindowParams.y = y - mDragPointYOffset; mWindowParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; mWindowParams.width = ViewGroup.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 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS; mWindowParams.format = PixelFormat.TRANSLUCENT; mWindowParams.windowAnimations = 0; Context context = getContext(); ImageView v = new ImageView(context); v.setImageBitmap(bitmap); WindowManager mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); mWindowManager.addView(v, mWindowParams); mDragView = v; mHiddenView = item; mHiddenView.setVisibility(INVISIBLE); } // destroy drag view private void stopDrag() { if (mHiddenView != null) { mHiddenView.setVisibility(VISIBLE); mHiddenView = null; } if (mDragView != null) { mDragView.setVisibility(GONE); WindowManager wm = (WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE); wm.removeView(mDragView); mDragView.setImageDrawable(null); mDragView = null; } } /** * Interface for use in class */ public interface DragListener { void onDrag(int from, int to); } }