@Override
  public boolean onTouchEvent(MotionEvent ev) {
    final int action = ev.getAction();
    final int x = (int) ev.getX();
    final int y = (int) ev.getY();

    // [shravan.mahankali] dynamically find the dragger object and let user drag the item
    // only if touched on dragger and not otherwise.
    if (action == MotionEvent.ACTION_DOWN) {
      int startPos = pointToPosition(x, y);
      if (startPos != INVALID_POSITION) {
        int mItemPosition = startPos - getFirstVisiblePosition();
        View grabber = getChildAt(mItemPosition).findViewById(draggerId);
        int mDragPointY = y - grabber.getTop();

        int[] grabberLocationOnScreen = new int[2];
        grabber.getLocationOnScreen(grabberLocationOnScreen);

        if (x >= grabber.getLeft()
            && x <= grabber.getRight()
            && mDragPointY >= grabber.getTop()
            && mDragPointY <= grabberLocationOnScreen[1]) mDragMode = true;
      }
    }

    if (!mDragMode) return super.onTouchEvent(ev);

    switch (action) {
      case MotionEvent.ACTION_DOWN:
        mStartPosition = pointToPosition(x, y);
        if (mStartPosition != INVALID_POSITION) {
          int mItemPosition = mStartPosition - getFirstVisiblePosition();
          mDragPointOffset = y - getChildAt(mItemPosition).getTop();
          mDragPointOffset -= ((int) ev.getRawY()) - y;
          startDrag(mItemPosition, y);
          drag(0, y); // replace 0 with x if desired
        }
        break;
      case MotionEvent.ACTION_MOVE:
        drag(0, y); // replace 0 with x if desired
        break;
      case MotionEvent.ACTION_CANCEL:
      case MotionEvent.ACTION_UP:
      default:
        mDragMode = false;
        mEndPosition = pointToPosition(x, y);
        stopDrag(mStartPosition - getFirstVisiblePosition());
        if (mDropListener != null
            && mStartPosition != INVALID_POSITION
            && mEndPosition != INVALID_POSITION) mDropListener.onDrop(mStartPosition, mEndPosition);
        break;
    }
    return true;
  }
  @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 && x < 40) {
      mDragMode = true;
    }

    if (!mDragMode) return super.onTouchEvent(ev);

    switch (action) {
      case MotionEvent.ACTION_DOWN:
        mStartPosition = pointToPosition(x, y);
        if (mStartPosition != INVALID_POSITION) {
          int mItemPosition = mStartPosition - getFirstVisiblePosition();
          mDragItemY = getChildAt(mItemPosition).getTop();
          mDragPointOffset = y - mDragItemY;
          mDragPointOffset -= ((int) ev.getRawY()) - y;
          startDrag(mItemPosition, y);
          drag(x, y);
        }
        break;
      case MotionEvent.ACTION_MOVE:
        drag(x, y);
        break;
      case MotionEvent.ACTION_CANCEL:
      case MotionEvent.ACTION_UP:
      default:
        mDragMode = false;
        mEndPosition = pointToPosition(x, y);
        stopDrag(mStartPosition - getFirstVisiblePosition(), x, y);
        if (mDropListener != null
            && mStartPosition != INVALID_POSITION
            && mEndPosition != INVALID_POSITION) mDropListener.onDrop(mStartPosition, mEndPosition);
        break;
    }
    return true;
  }