/**
   * Shuffle list items given new float position.
   *
   * @param floatPos
   */
  private boolean shuffleItems(int floatPos) {

    // Log.d("mobeta", "float position: " + floatPos);
    // Log.d("mobeta", "exp position: " + mExpDragPos);
    // Log.d("mobeta", "first position: " + getFirstVisiblePosition() +
    // " height: " + getChildAt(0).getHeight());

    if (floatPos != mExpDragPos) {
      // if we get here, the ListView is inconsistent with the
      // floating view

      // Log.d("mobeta",
      // "collapsing="+mExpDragPos+" expanding="+floatPos);
      collapseItem(mExpDragPos);
      expandItem(floatPos);

      // callback
      if (mDragListener != null) {
        final int numHeaders = getHeaderViewsCount();
        mDragListener.drag(mExpDragPos - numHeaders, floatPos - numHeaders);
      }

      // update state
      mExpDragPos = floatPos;
      updateListState();

      return true;
    } else {
      return false;
    }
  }
  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    if ((mDragListener != null || mDropListener != null) && mDragView != null) {
      int action = ev.getAction();
      switch (action) {
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
          Rect r = mTempRect;
          mDragView.getDrawingRect(r);
          stopDragging();
          if (mDropListener != null && mDragPos >= 0 && mDragPos < getCount()) {
            mDropListener.drop(mFirstDragPos, mDragPos);
          }
          unExpandViews(false);
          break;

        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
          int x = (int) ev.getX();
          int y = (int) ev.getY();
          dragView(x, y);
          int itemnum = getItemForPosition(y);
          if (itemnum >= 0) {
            if (action == MotionEvent.ACTION_DOWN || itemnum != mDragPos) {
              if (mDragListener != null) {
                mDragListener.drag(mDragPos, itemnum);
              }
              mDragPos = itemnum;
              doExpansion();
            }
            int speed = 0;
            adjustScrollBounds(y);
            if (y > mLowerBound) {
              // scroll the list up a bit
              speed = y > (mHeight + mLowerBound) / 2 ? 16 : 4;
            } else if (y < mUpperBound) {
              // scroll the list down a bit
              speed = y < mUpperBound / 2 ? -16 : -4;
            }
            if (speed != 0) {
              int ref = pointToPosition(0, mHeight / 2);
              if (ref == AdapterView.INVALID_POSITION) {
                // we hit a divider or an invisible view, check
                // somewhere else
                ref = pointToPosition(0, mHeight / 2 + getDividerHeight() + 64);
              }
              View v = getChildAt(ref - getFirstVisiblePosition());
              if (v != null) {
                int pos = v.getTop();
                setSelectionFromTop(ref, pos - speed);
              }
            }
          }
          break;
      }
      return true;
    }
    return super.onTouchEvent(ev);
  }
  @Override
  public boolean onTouchEvent(MotionEvent ev) {
    if (mGestureDetector != null) {
      mGestureDetector.onTouchEvent(ev);
    }
    if ((mDragListener != null || mDropListener != null) && mDragView != null) {
      int action = ev.getAction();
      switch (action) {
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
          Rect r = mTempRect;
          mDragView.getDrawingRect(r);
          stopDragging();
          if (mRemoveMode == SLIDE && ev.getX() > r.right * 3 / 4) {
            if (mRemoveListener != null) {
              mRemoveListener.remove(mSrcDragPos);
            }
            unExpandViews(true);
          } else {
            if (mDropListener != null && mDragPos >= 0 && mDragPos < getCount()) {
              mDropListener.drop(mSrcDragPos, mDragPos);
            }
            unExpandViews(false);
          }
          break;

        case MotionEvent.ACTION_DOWN:
        case MotionEvent.ACTION_MOVE:
          int x = (int) ev.getX();
          int y = (int) ev.getY();
          dragView(x, y);
          int itemnum = getItemForPosition(y);
          if (itemnum >= 0) {
            if (action == MotionEvent.ACTION_DOWN || itemnum != mDragPos) {
              if (mDragListener != null) {
                mDragListener.drag(mDragPos, itemnum);
              }
              mDragPos = itemnum;
              doExpansion();
            }
            int speed = 0;
            adjustScrollBounds(y);
            if (y > mLowerBound) {
              // scroll the list up a bit
              if (getLastVisiblePosition() < getCount() - 1) {
                speed = y > (mHeight + mLowerBound) / 2 ? 16 : 4;
              } else {
                speed = 1;
              }
            } else if (y < mUpperBound) {
              // scroll the list down a bit
              speed = y < mUpperBound / 2 ? -16 : -4;
              if (getFirstVisiblePosition() == 0 && getChildAt(0).getTop() >= getPaddingTop()) {
                // if we're already at the top, don't try to scroll, because
                // it causes the framework to do some extra drawing that messes
                // up our animation
                speed = 0;
              }
            }
            if (speed != 0) {
              smoothScrollBy(speed, 30);
            }
          }
          break;
      }
      return true;
    }
    return super.onTouchEvent(ev);
  }