protected MotionEvent createLongLeftMoveEvent() {
   MotionEvent event = mock(MotionEvent.class);
   when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE);
   when(event.getX()).thenReturn(50f);
   when(event.getY()).thenReturn(150f);
   when(event.getX(0)).thenReturn(50f);
   when(event.getY(0)).thenReturn(150f);
   when(event.getHistorySize()).thenReturn(1);
   when(event.getHistoricalX(eq(0))).thenReturn(100f);
   when(event.getHistoricalY(eq(0))).thenReturn(200f);
   when(event.getHistoricalX(eq(0), eq(0))).thenReturn(100f);
   when(event.getHistoricalY(eq(0), eq(0))).thenReturn(200f);
   return event;
 }
예제 #2
0
  @Override
  public boolean onTouchEvent(MotionEvent event) {

    float mCurX;
    float mCurY;

    // API level 9 and above supports "Major" property on event which
    // gives
    // the size of the touch area at the point of contact
    // so for now we just hard code
    float TOUCH_AREA_SIZE = penWidth;

    int action = event.getAction();
    if (action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL) {
      int N = event.getHistorySize();
      int P = event.getPointerCount();
      for (int i = 0; i < N; i++) {
        for (int j = 0; j < P; j++) {
          mCurX = event.getHistoricalX(j, i);
          mCurY = event.getHistoricalY(j, i);
          drawPoint(mCurX, mCurY, event.getHistoricalPressure(j, i), TOUCH_AREA_SIZE);
        }
      }
      for (int j = 0; j < P; j++) {
        mCurX = event.getX(j);
        mCurY = event.getY(j);
        drawPoint(mCurX, mCurY, event.getPressure(j), TOUCH_AREA_SIZE);
      }
    }
    unsaved = true;
    return true;
  }
  @Test
  public void onTouchMoveAction_2ndLeftDragInRightEnd_overscrollLeftFurther() throws Exception {

    // Arrange

    // Bring UUT to a left-overscroll state
    MotionEvent event1 = createShortLeftMoveEvent();

    when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
    when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);

    HorizontalOverScrollBounceEffectDecorator uut = getUUT();
    uut.onTouch(mView, event1);
    reset(mView);

    // Create 2nd left-drag event
    MotionEvent event2 = createLongLeftMoveEvent();

    // Act

    boolean ret = uut.onTouch(mView, event2);

    // Assert

    float expectedTransX =
        (event2.getX() - event2.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
    verify(mView).setTranslationX(expectedTransX);
    verify(mView, never()).setTranslationY(anyFloat());
    assertTrue(ret);
  }
예제 #4
0
 public boolean onTouch(View view, MotionEvent event) {
   float x = event.getX();
   float y = event.getY();
   switch (event.getAction()) {
     case MotionEvent.ACTION_DOWN:
       path.moveTo(x, y);
       return true;
     case MotionEvent.ACTION_UP:
     case MotionEvent.ACTION_MOVE:
       l = x;
       r = x;
       t = y;
       b = y;
       for (int i = 0; i < event.getHistorySize(); i++) {
         float newX = event.getHistoricalX(i);
         float newY = event.getHistoricalY(i);
         path.lineTo(newX, newY);
         l = newX < l ? newX : l;
         t = newY < t ? newY : t;
         r = newX > r ? newX : r;
         b = newY > b ? newY : b;
       }
       rect.set(l, t, r, b);
       Log.d("TAG", rect.toShortString());
       invalidate(
           (int) rect.left - 5, (int) rect.top - 5, (int) rect.right + 5, (int) rect.bottom + 5);
       break;
     default:
   }
   return super.onTouchEvent(event);
 }
예제 #5
0
  // @!ANDROID-4
  private static int getAction(int index, MotionEvent event) {
    int action = event.getAction();
    if (action == MotionEvent.ACTION_MOVE) {
      int hsz = event.getHistorySize();
      if (hsz > 0) {
        if (Math.abs(event.getX(index) - event.getHistoricalX(index, hsz - 1)) > 1
            || Math.abs(event.getY(index) - event.getHistoricalY(index, hsz - 1)) > 1) return 1;
        else return 2;
      }
      return 1;
    }

    switch (index) {
      case 0:
        if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_1_DOWN)
          return 0;
        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_1_UP) return 3;
        break;

      case 1:
        if (action == MotionEvent.ACTION_POINTER_2_DOWN
            || action == MotionEvent.ACTION_POINTER_DOWN) return 0;
        if (action == MotionEvent.ACTION_POINTER_2_UP || action == MotionEvent.ACTION_POINTER_UP)
          return 3;
        break;

      case 2:
        if (action == MotionEvent.ACTION_POINTER_3_DOWN
            || action == MotionEvent.ACTION_POINTER_DOWN) return 0;
        if (action == MotionEvent.ACTION_POINTER_3_UP || action == MotionEvent.ACTION_POINTER_UP)
          return 3;
        break;
    }
    return 2;
  }
예제 #6
0
 @Override
 public boolean onTouchEvent(final ViewGroup view, final MotionEvent event) {
   if (mIsVerticalScrolling && !mController.isScrolling() || mShouldDisableScroll) return true;
   switch (event.getAction()) {
     case MotionEvent.ACTION_DOWN:
       {
         mTempDeltaX = 0;
         mTotalMoveX = 0;
         mTotalMoveY = 0;
         mActualMoveX = 0;
         mIsVerticalScrolling = false;
         mController.reset();
         break;
       }
     case MotionEvent.ACTION_MOVE:
       {
         final int hist_size = event.getHistorySize();
         if (hist_size == 0) {
           break;
         }
         final float distanceX = mTempDeltaX = event.getX() - event.getHistoricalX(0);
         mActualMoveX = mTotalMoveX += mTempDeltaX;
         mController.scrollBy((int) -distanceX);
         break;
       }
   }
   return true;
 }
예제 #7
0
  private void track(MotionEvent event) {
    mX.saveTouchPos();
    mY.saveTouchPos();

    for (int i = 0; i < event.getHistorySize(); i++) {
      track(
          event.getHistoricalX(0, i), event.getHistoricalY(0, i), event.getHistoricalEventTime(i));
    }
    track(event.getX(0), event.getY(0), event.getEventTime());

    if (stopped()) {
      if (mState == PanZoomState.PANNING) {
        setState(PanZoomState.PANNING_HOLD);
      } else if (mState == PanZoomState.PANNING_LOCKED) {
        setState(PanZoomState.PANNING_HOLD_LOCKED);
      } else {
        // should never happen, but handle anyway for robustness
        Log.e(LOGTAG, "Impossible case " + mState + " when stopped in track");
        setState(PanZoomState.PANNING_HOLD_LOCKED);
      }
    }

    mX.startPan();
    mY.startPan();
    updatePosition();
  }
예제 #8
0
  /**
   * Extracts the touch point data from a MotionEvent, converts each point into a marshallable
   * object and passes the set of points to the JNI layer to be transmitted to the remote host.
   *
   * @param event The event to send to the remote host for injection. NOTE: This object must be
   *     updated to represent the remote machine's coordinate system before calling this function.
   */
  public void sendTouchEvent(MotionEvent event) {
    int action = event.getActionMasked();
    TouchEventData.EventType touchEventType = TouchEventData.EventType.fromMaskedAction(action);
    List<TouchEventData> touchEventList = new ArrayList<TouchEventData>();

    if (action == MotionEvent.ACTION_MOVE) {
      // In order to process all of the events associated with an ACTION_MOVE event, we need
      // to walk the list of historical events in order and add each event to our list, then
      // retrieve the current move event data.
      int pointerCount = event.getPointerCount();
      int historySize = event.getHistorySize();
      for (int h = 0; h < historySize; ++h) {
        for (int p = 0; p < pointerCount; ++p) {
          touchEventList.add(
              new TouchEventData(
                  event.getPointerId(p),
                  event.getHistoricalX(p, h),
                  event.getHistoricalY(p, h),
                  event.getHistoricalSize(p, h),
                  event.getHistoricalSize(p, h),
                  event.getHistoricalOrientation(p, h),
                  event.getHistoricalPressure(p, h)));
        }
      }

      for (int p = 0; p < pointerCount; p++) {
        touchEventList.add(
            new TouchEventData(
                event.getPointerId(p),
                event.getX(p),
                event.getY(p),
                event.getSize(p),
                event.getSize(p),
                event.getOrientation(p),
                event.getPressure(p)));
      }
    } else {
      // For all other events, we only want to grab the current/active pointer.  The event
      // contains a list of every active pointer but passing all of of these to the host can
      // cause confusion on the remote OS side and result in broken touch gestures.
      int activePointerIndex = event.getActionIndex();
      touchEventList.add(
          new TouchEventData(
              event.getPointerId(activePointerIndex),
              event.getX(activePointerIndex),
              event.getY(activePointerIndex),
              event.getSize(activePointerIndex),
              event.getSize(activePointerIndex),
              event.getOrientation(activePointerIndex),
              event.getPressure(activePointerIndex)));
    }

    if (!touchEventList.isEmpty()) {
      mInjector.sendTouchEvent(touchEventType, touchEventList.toArray(new TouchEventData[0]));
    }
  }
예제 #9
0
  @Override
  public boolean onTouchEvent(MotionEvent event) {

    float mCurX;
    float mCurY;

    ArrayList<Point> eraserpoints = new ArrayList<Point>();

    int action = event.getAction();
    if (action != MotionEvent.ACTION_UP && action != MotionEvent.ACTION_CANCEL) {
      // Log.d(TAG, "PEN UP");
    }
    if (action == MotionEvent.ACTION_DOWN) {
      // start recording points
      mCurrentPath = new Path();
      mCurrentPath.moveTo(event.getX(), event.getY());
    }
    if (action == MotionEvent.ACTION_MOVE) {
      // start recording points
      int N = event.getHistorySize();
      int P = event.getPointerCount();
      for (int i = 0; i < N; i++) {
        for (int j = 0; j < P; j++) {
          mCurX = event.getHistoricalX(j, i);
          mCurY = event.getHistoricalY(j, i);

          if (mEraserMode == true) {
            if (eraserpoints != null) {
              eraserpoints.add(new Point(Math.round(mCurX), Math.round(mCurY)));
            } else {
              Log.e(TAG, "no eraserpoints array defined, skipping adding erase point");
            }
          } else {
            if (mCurrentPath != null) {
              mCurrentPath.lineTo(mCurX, mCurY);
            } else {
              Log.e(TAG, "NO PATH TO ADD POINT" + mCurX + "," + mCurY);
            }
          }
        }
      }

      if (mCurrentPath != null) {
        mCurrentPath.lineTo(event.getX(), event.getY());
        mCanvas.drawPath(mCurrentPath, (mEraserMode == true ? mEraserPainter : mPenPainter));
        invalidate();
      } else {
        Log.e(TAG, "Missing CurrentPath object");
      }
    }
    mUnsaved = true;
    return true;
  }
예제 #10
0
 public void c(MotionEvent paramMotionEvent) {
   int j = paramMotionEvent.getHistorySize();
   int i = 0;
   while (i < j) {
     a(
         paramMotionEvent.getActionMasked(),
         paramMotionEvent.getHistoricalX(0, i),
         paramMotionEvent.getHistoricalY(0, i));
     i += 1;
   }
   a(paramMotionEvent.getActionMasked(), paramMotionEvent.getX(), paramMotionEvent.getY());
 }
예제 #11
0
 @Override
 public boolean onTouch(final View view, final MotionEvent event) {
   switch (event.getAction()) {
     case MotionEvent.ACTION_DOWN:
       {
         mTempDeltaX = 0;
         mTotalMoveX = 0;
         mIsScrolling = false;
         // final View layout = mParent.getRightPaneLayout();
         mShouldDisableScroll =
             !(mContext instanceof DualPaneActivity
                 && ((DualPaneActivity) mContext).isRightPaneUsed());
         if (!mShouldDisableScroll) {
           mController.reset();
         } else return false;
         break;
       }
     case MotionEvent.ACTION_MOVE:
       {
         if (mShouldDisableScroll) return false;
         final int hist_size = event.getHistorySize();
         if (hist_size == 0) {
           break;
         }
         final float distanceX = mTempDeltaX = event.getX() - event.getHistoricalX(0);
         mTotalMoveX += mTempDeltaX;
         if (Math.abs(mTotalMoveX) >= mScaledTouchSlop) {
           mIsScrolling = true;
         }
         if (mIsScrolling) {
           mController.scrollBy((int) -distanceX);
         }
         break;
       }
     case MotionEvent.ACTION_UP:
       {
         if (mIsScrolling) {
           mController.release(-mTempDeltaX, -mTotalMoveX);
         }
         mTempDeltaX = 0;
         mTotalMoveX = 0;
         mIsScrolling = false;
         if (mShouldDisableScroll) {
           mShouldDisableScroll = false;
           return false;
         }
         mShouldDisableScroll = false;
         break;
       }
   }
   return true;
 }
  /**
   * When over-scroll has already started (to the left in this case) and suddenly the user changes
   * their mind and scrolls a bit in the other direction: <br>
   * We expect the <b>touch to still be intercepted</b> in that case, and the <b>overscroll to
   * remain in effect</b>.
   */
  @Test
  public void onTouchMoveAction_dragRightWhenLeftOverscolled_continueOverscrollingRight()
      throws Exception {

    // Arrange

    // In left & right tests we use equal ratios to avoid the effect's under-scroll handling
    final float touchDragRatioFwd = 3f;
    final float touchDragRatioBck = 3f;

    // Bring UUT to a left-overscroll state
    when(mViewAdapter.isInAbsoluteStart()).thenReturn(false);
    when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true);

    HorizontalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
    MotionEvent eventMoveLeft = createLongLeftMoveEvent();
    uut.onTouch(mView, eventMoveLeft);
    reset(mView);

    float startTransX =
        (eventMoveLeft.getX() - eventMoveLeft.getHistoricalX(0)) / touchDragRatioFwd;
    when(mView.getTranslationX()).thenReturn(startTransX);

    // Create the right-drag event
    MotionEvent eventMoveRight = createShortRightMoveEvent();

    // Act

    boolean ret = uut.onTouch(mView, eventMoveRight);

    // Assert

    float expectedTransX =
        startTransX
            + (eventMoveRight.getX() - eventMoveRight.getHistoricalX(0)) / touchDragRatioBck;
    verify(mView).setTranslationX(expectedTransX);
    verify(mView, never()).setTranslationY(anyFloat());
    assertTrue(ret);
  }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float eventX = event.getX();
    float eventY = event.getY();

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        path.moveTo(eventX, eventY);
        lastTouchX = eventX;
        lastTouchY = eventY;
        // There is no end point yet, so don't waste cycles invalidating.
        return true;

      case MotionEvent.ACTION_MOVE:
      case MotionEvent.ACTION_UP:
        // Start tracking the dirty region.
        resetDirtyRect(eventX, eventY);

        // When the hardware tracks events faster than they are delivered, the
        // event will contain a history of those skipped points.
        int historySize = event.getHistorySize();
        for (int i = 0; i < historySize; i++) {
          float historicalX = event.getHistoricalX(i);
          float historicalY = event.getHistoricalY(i);
          expandDirtyRect(historicalX, historicalY);
          path.lineTo(historicalX, historicalY);
        }

        // After replaying history, connect the line to the touch point.
        path.lineTo(eventX, eventY);
        break;

      default:
        Log.d("default", "Ignored touch event: " + event.toString());
        return false;
    }

    // Include half the stroke width to avoid clipping.
    invalidate(
        (int) (dirtyRect.left - HALF_STROKE_WIDTH),
        (int) (dirtyRect.top - HALF_STROKE_WIDTH),
        (int) (dirtyRect.right + HALF_STROKE_WIDTH),
        (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));

    lastTouchX = eventX;
    lastTouchY = eventY;

    return true;
  }
 /**
  * Add a user's movement to the tracker. You should call this for the initial {@link
  * MotionEvent#ACTION_DOWN}, the following {@link MotionEvent#ACTION_MOVE} events that you
  * receive, and the final {@link MotionEvent#ACTION_UP}. You can, however, call this for whichever
  * events you desire.
  *
  * @param ev The MotionEvent you received and would like to track.
  */
 public void addMovement(MotionEvent ev) {
   final int mN = ev.getHistorySize();
   if (++mLastTouch >= NUM_PAST) {
     mLastTouch = 0;
   }
   for (int i = 0; i < mN; ++i) {
     mPastX[mLastTouch] = ev.getHistoricalX(i);
     mPastY[mLastTouch] = ev.getHistoricalY(i);
     mPastTime[mLastTouch] = ev.getHistoricalEventTime(i);
     if (++mLastTouch >= NUM_PAST) {
       mLastTouch = 0;
     }
   }
   mPastX[mLastTouch] = ev.getX();
   mPastY[mLastTouch] = ev.getY();
   mPastTime[mLastTouch] = ev.getEventTime();
 }
예제 #15
0
 @Override
 public boolean onInterceptTouchEvent(final ViewGroup view, final MotionEvent event) {
   mShouldDisableScroll =
       !(isTouchEventHandled(view, event)
           || mContext instanceof DualPaneActivity
               && ((DualPaneActivity) mContext).isRightPaneUsed());
   switch (event.getAction()) {
     case MotionEvent.ACTION_DOWN:
       {
         mFirstDownHandled = !mShouldDisableScroll;
         mTempDeltaX = 0;
         mTotalMoveX = 0;
         mTotalMoveY = 0;
         mActualMoveX = 0;
         mIsVerticalScrolling = false;
         if (mFirstDownHandled) {
           mParent.animateOpen();
         }
         break;
       }
     case MotionEvent.ACTION_MOVE:
       {
         final int hist_size = event.getHistorySize();
         if (hist_size == 0) {
           break;
         }
         mTempDeltaX = event.getX() - event.getHistoricalX(0);
         mTotalMoveX += mTempDeltaX;
         final float deltaY = event.getY() - event.getHistoricalY(0);
         mTotalMoveY += deltaY;
         if (Math.abs(mTempDeltaX) > Math.abs(deltaY)
             && !mIsVerticalScrolling
             && Math.abs(mTotalMoveX) >= mScaledTouchSlop) return true;
         if (Math.abs(mTempDeltaX) < Math.abs(deltaY)
             && Math.abs(mTotalMoveY) >= mScaledTouchSlop) {
           mIsVerticalScrolling = true;
           return false;
         }
         break;
       }
   }
   return false;
 }
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    float eventX = event.getX();
    float eventY = event.getY();

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        path.moveTo(eventX, eventY);

        lastTouchX = eventX;
        lastTouchY = eventY;
        return true;

      case MotionEvent.ACTION_MOVE:

      case MotionEvent.ACTION_UP:
        resetDirtyRect(eventX, eventY);
        int historySize = event.getHistorySize();
        for (int i = 0; i < historySize; i++) {
          float historicalX = event.getHistoricalX(i);
          float historicalY = event.getHistoricalY(i);

          expandDirtyRect(historicalX, historicalY);
          path.lineTo(historicalX, historicalY);
        }
        path.lineTo(eventX, eventY);
        break;

      default:
        return false;
    }

    invalidate(
        (int) (dirtyRect.left - HALF_STROKE_WIDTH),
        (int) (dirtyRect.top - HALF_STROKE_WIDTH),
        (int) (dirtyRect.right + HALF_STROKE_WIDTH),
        (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));

    lastTouchX = eventX;
    lastTouchY = eventY;

    return true;
  }
 private int detectSwipe(MotionEvent move) {
   final int historySize = move.getHistorySize();
   final int pointerCount = move.getPointerCount();
   for (int p = 0; p < pointerCount; p++) {
     final int pointerId = move.getPointerId(p);
     final int i = findIndex(pointerId);
     if (i != UNTRACKED_POINTER) {
       for (int h = 0; h < historySize; h++) {
         final long time = move.getHistoricalEventTime(h);
         final float x = move.getHistoricalX(p, h);
         final float y = move.getHistoricalY(p, h);
         final int swipe = detectSwipe(i, time, x, y);
         if (swipe != SWIPE_NONE) {
           return swipe;
         }
       }
       final int swipe = detectSwipe(i, move.getEventTime(), move.getX(p), move.getY(p));
       if (swipe != SWIPE_NONE) {
         return swipe;
       }
     }
   }
   return SWIPE_NONE;
 }
  @Test
  public void onTouchMoveAction_dragRightInLeftEnd_overscrollRight() throws Exception {

    // Arrange

    MotionEvent event = createShortRightMoveEvent();

    when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
    when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);

    HorizontalOverScrollBounceEffectDecorator uut = getUUT();

    // Act

    boolean ret = uut.onTouch(mView, event);

    // Assert

    float expectedTransX =
        (event.getX() - event.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
    verify(mView).setTranslationX(expectedTransX);
    verify(mView, never()).setTranslationY(anyFloat());
    assertTrue(ret);
  }
예제 #19
0
  private void handleActionMove(MotionEvent event) {
    // Handle all recent motion events so we don't skip any cells even when the device
    // is busy...
    final int historySize = event.getHistorySize();
    for (int i = 0; i < historySize + 1; i++) {
      final float x = i < historySize ? event.getHistoricalX(i) : event.getX();
      final float y = i < historySize ? event.getHistoricalY(i) : event.getY();
      final int patternSizePreHitDetect = mPattern.size();
      Cell hitCell = detectAndAddHit(x, y);
      final int patternSize = mPattern.size();
      if (hitCell != null && patternSize == 1) {
        mPatternInProgress = true;
        notifyPatternStarted();
      }
      // note current x and y for rubber banding of in progress patterns
      final float dx = Math.abs(x - mInProgressX);
      final float dy = Math.abs(y - mInProgressY);
      if (dx + dy > mSquareWidth * 0.01f) {
        float oldX = mInProgressX;
        float oldY = mInProgressY;

        mInProgressX = x;
        mInProgressY = y;

        if (mPatternInProgress && patternSize > 0) {
          final ArrayList<Cell> pattern = mPattern;
          final float radius = mSquareWidth * mDiameterFactor * 0.5f;

          final Cell lastCell = pattern.get(patternSize - 1);

          float startX = getCenterXForColumn(lastCell.column);
          float startY = getCenterYForRow(lastCell.row);

          float left;
          float top;
          float right;
          float bottom;

          final Rect invalidateRect = mInvalidate;

          if (startX < x) {
            left = startX;
            right = x;
          } else {
            left = x;
            right = startX;
          }

          if (startY < y) {
            top = startY;
            bottom = y;
          } else {
            top = y;
            bottom = startY;
          }

          // Invalidate between the pattern's last cell and the current location
          invalidateRect.set(
              (int) (left - radius),
              (int) (top - radius),
              (int) (right + radius),
              (int) (bottom + radius));

          if (startX < oldX) {
            left = startX;
            right = oldX;
          } else {
            left = oldX;
            right = startX;
          }

          if (startY < oldY) {
            top = startY;
            bottom = oldY;
          } else {
            top = oldY;
            bottom = startY;
          }

          // Invalidate between the pattern's last cell and the previous location
          invalidateRect.union(
              (int) (left - radius),
              (int) (top - radius),
              (int) (right + radius),
              (int) (bottom + radius));

          // Invalidate between the pattern's new cell and the pattern's previous cell
          if (hitCell != null) {
            startX = getCenterXForColumn(hitCell.column);
            startY = getCenterYForRow(hitCell.row);

            if (patternSize >= 2) {
              // (re-using hitcell for old cell)
              hitCell = pattern.get(patternSize - 1 - (patternSize - patternSizePreHitDetect));
              oldX = getCenterXForColumn(hitCell.column);
              oldY = getCenterYForRow(hitCell.row);

              if (startX < oldX) {
                left = startX;
                right = oldX;
              } else {
                left = oldX;
                right = startX;
              }

              if (startY < oldY) {
                top = startY;
                bottom = oldY;
              } else {
                top = oldY;
                bottom = startY;
              }
            } else {
              left = right = startX;
              top = bottom = startY;
            }

            final float widthOffset = mSquareWidth / 2f;
            final float heightOffset = mSquareHeight / 2f;

            invalidateRect.set(
                (int) (left - widthOffset),
                (int) (top - heightOffset),
                (int) (right + widthOffset),
                (int) (bottom + heightOffset));
          }

          invalidate(invalidateRect);
        } else {
          invalidate();
        }
      }
    }
  }
예제 #20
0
  public boolean onTestMove(MotionEvent event) {

    float xInit = event.getHistoricalX(0);
    float yInit = event.getHistoricalY(0);

    float xNow = event.getX();
    float yNow = event.getY();

    Rect viewRect = new Rect();
    if (!isMove) {
      for (int i = 0; i < getChildCount(); i++) {
        View child = getChildAt(i);
        int left = child.getLeft();
        int right = child.getRight();
        int top = child.getTop();
        int bottom = child.getBottom();
        viewRect.set(left, top, right, bottom);
        if (viewRect.contains((int) xInit, (int) yInit)) {
          if (yNow > yInit) {

            Log.d("relache", "pass� in ");
            if (mOnItemMoveListener != null) {
              mOnItemMoveListener.onTouch(child, event);
              this.childSelected = child;
            }

            if (mOnItemClicked != null) {
              mOnItemClicked.onItemClick(
                  HorizontalListView.this,
                  child,
                  mLeftViewIndex + 1 + i,
                  mAdapter.getItemId(mLeftViewIndex + 1 + i));
            }

            isMove = true;
            return true;
          }
        }
      }
    } else {
      mOnItemMoveListener.onTouch(childSelected, event);

      if (event.getAction() == MotionEvent.ACTION_UP) {
        int left = this.getLeft();
        int right = this.getRight();
        int top = this.getTop();
        int bottom = this.getBottom();
        Rect rect = new Rect(left, top, right, bottom);

        if (!rect.contains((int) xNow, (int) yNow)) {

          if (mOnItemOutListener != null) {
            mOnItemOutListener.onTouch(this.childSelected, event);
          }
        }

        isMove = false;
        return false;
      }

      return true;
    }

    return false;
  }
예제 #21
0
  private void handleMove(MotionEvent event) {
    int activeTarget = -1;
    final int historySize = event.getHistorySize();
    ArrayList<TargetDrawable> targets = mTargetDrawables;
    int ntargets = targets.size();
    float x = 0.0f;
    float y = 0.0f;
    int actionIndex = event.findPointerIndex(mPointerId);

    if (actionIndex == -1) {
      return; // no data for this pointer
    }

    for (int k = 0; k < historySize + 1; k++) {
      float eventX =
          k < historySize ? event.getHistoricalX(actionIndex, k) : event.getX(actionIndex);
      float eventY =
          k < historySize ? event.getHistoricalY(actionIndex, k) : event.getY(actionIndex);
      // tx and ty are relative to wave center
      float tx = eventX - mWaveCenterX;
      float ty = eventY - mWaveCenterY;
      float touchRadius = (float) Math.sqrt(dist2(tx, ty));
      final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;
      float limitX = tx * scale;
      float limitY = ty * scale;
      double angleRad = Math.atan2(-ty, tx);

      if (!mDragging) {
        trySwitchToFirstTouchState(eventX, eventY);
      }

      if (mDragging) {
        // For multiple targets, snap to the one that matches
        final float snapRadius = mRingScaleFactor * mOuterRadius - mSnapMargin;
        final float snapDistance2 = snapRadius * snapRadius;
        // Find first target in range
        for (int i = 0; i < ntargets; i++) {
          TargetDrawable target = targets.get(i);

          double targetMinRad = (i - 0.5) * 2 * Math.PI / ntargets;
          double targetMaxRad = (i + 0.5) * 2 * Math.PI / ntargets;
          if (target.isEnabled()) {
            boolean angleMatches =
                (angleRad > targetMinRad && angleRad <= targetMaxRad)
                    || (angleRad + 2 * Math.PI > targetMinRad
                        && angleRad + 2 * Math.PI <= targetMaxRad);
            if (angleMatches && (dist2(tx, ty) > snapDistance2)) {
              activeTarget = i;
            }
          }
        }
      }
      x = limitX;
      y = limitY;
    }

    if (!mDragging) {
      return;
    }

    if (activeTarget != -1) {
      switchToState(STATE_SNAP, x, y);
      updateGlowPosition(x, y);
    } else {
      switchToState(STATE_TRACKING, x, y);
      updateGlowPosition(x, y);
    }

    if (mActiveTarget != activeTarget) {
      // Defocus the old target
      if (mActiveTarget != -1) {
        TargetDrawable target = targets.get(mActiveTarget);
        target.setState(TargetDrawable.STATE_INACTIVE);
      }
      // Focus the new target
      if (activeTarget != -1) {
        TargetDrawable target = targets.get(activeTarget);
        target.setState(TargetDrawable.STATE_FOCUSED);
        final AccessibilityManager accessibilityManager =
            (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
        if (accessibilityManager.isEnabled()) {
          String targetContentDescription = getTargetDescription(activeTarget);
          announceForAccessibility(targetContentDescription);
        }
      }
    }
    mActiveTarget = activeTarget;
  }
예제 #22
0
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    int action = event.getAction();
    switch (action) {
      case MotionEvent.ACTION_DOWN:
        downX = event.getX();
        downY = event.getY();
        if (mPropagateClicks) propagatePressed(true);
        break;

      case MotionEvent.ACTION_MOVE:
        try {
          if (mPropagateClicks) {
            float xDeltaTotal = event.getX() - downX;
            float yDeltaTotal = event.getY() - downY;
            if (Math.abs(xDeltaTotal) >= CLICK_SENSITIVITY
                || Math.abs(yDeltaTotal) >= CLICK_SENSITIVITY) {
              propagatePressed(false);
            }
          }

          float xDelta = event.getX() - downX;
          float yDelta = event.getY() - downY;
          if (event.getHistorySize() > 0) {
            xDelta = event.getX() - event.getHistoricalX(0);
            yDelta = event.getY() - event.getHistoricalY(0);
          }

          if (Math.abs(xDelta) > Math.abs(yDelta)) {
            if (xDelta > 0 && getCurrentItem() == 0 && mPositionOffset == 0) {
              return false;
            } else if (xDelta < 0 && mPositionOffset == 0) {
              if (getAdapter() != null) {
                int current = getCurrentItem();
                int count = getAdapter().getCount();
                if (current >= (count - 1)) {
                  return false;
                }
              }
            }
            NestedViewPager.this.getParent().requestDisallowInterceptTouchEvent(true);
          }
        } catch (Exception e) {
          // nothing
        }
        break;

      case MotionEvent.ACTION_UP:
        if (mPropagateClicks) {
          propagatePressed(false);

          float xDelta = event.getX() - downX;
          float yDelta = event.getY() - downY;
          if (Math.abs(xDelta) < CLICK_SENSITIVITY && Math.abs(yDelta) < CLICK_SENSITIVITY) {
            propagateClicked();
          }
        }
        break;
    }
    return super.onTouchEvent(event);
  }