android.view.MotionEvent#getHistoricalX ( )源码实例Demo

下面列出了android.view.MotionEvent#getHistoricalX ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: openboard   文件: PointerTracker.java
private void onMoveEvent(final int x, final int y, final long eventTime, final MotionEvent me) {
    if (DEBUG_MOVE_EVENT) {
        printTouchEvent("onMoveEvent:", x, y, eventTime);
    }
    if (mIsTrackingForActionDisabled) {
        return;
    }

    if (sGestureEnabler.shouldHandleGesture() && me != null) {
        // Add historical points to gesture path.
        final int pointerIndex = me.findPointerIndex(mPointerId);
        final int historicalSize = me.getHistorySize();
        for (int h = 0; h < historicalSize; h++) {
            final int historicalX = (int)me.getHistoricalX(pointerIndex, h);
            final int historicalY = (int)me.getHistoricalY(pointerIndex, h);
            final long historicalTime = me.getHistoricalEventTime(h);
            onGestureMoveEvent(historicalX, historicalY, historicalTime,
                    false /* isMajorEvent */, null);
        }
    }

    if (isShowingMoreKeysPanel()) {
        final int translatedX = mMoreKeysPanel.translateX(x);
        final int translatedY = mMoreKeysPanel.translateY(y);
        mMoreKeysPanel.onMoveEvent(translatedX, translatedY, mPointerId, eventTime);
        onMoveKey(x, y);
        if (mIsInSlidingKeyInput) {
            sDrawingProxy.showSlidingKeyInputPreview(this);
        }
        return;
    }
    onMoveEventInternal(x, y, eventTime);
}
 
源代码2 项目: Indic-Keyboard   文件: PointerTracker.java
private void onMoveEvent(final int x, final int y, final long eventTime, final MotionEvent me) {
    if (DEBUG_MOVE_EVENT) {
        printTouchEvent("onMoveEvent:", x, y, eventTime);
    }
    if (mIsTrackingForActionDisabled) {
        return;
    }

    if (sGestureEnabler.shouldHandleGesture() && me != null) {
        // Add historical points to gesture path.
        final int pointerIndex = me.findPointerIndex(mPointerId);
        final int historicalSize = me.getHistorySize();
        for (int h = 0; h < historicalSize; h++) {
            final int historicalX = (int)me.getHistoricalX(pointerIndex, h);
            final int historicalY = (int)me.getHistoricalY(pointerIndex, h);
            final long historicalTime = me.getHistoricalEventTime(h);
            onGestureMoveEvent(historicalX, historicalY, historicalTime,
                    false /* isMajorEvent */, null);
        }
    }

    if (isShowingMoreKeysPanel()) {
        final int translatedX = mMoreKeysPanel.translateX(x);
        final int translatedY = mMoreKeysPanel.translateY(y);
        mMoreKeysPanel.onMoveEvent(translatedX, translatedY, mPointerId, eventTime);
        onMoveKey(x, y);
        if (mIsInSlidingKeyInput) {
            sDrawingProxy.showSlidingKeyInputPreview(this);
        }
        return;
    }
    onMoveEventInternal(x, y, eventTime);
}
 
源代码3 项目: ResearchStack   文件: SignatureView.java
@Override
public boolean onTouchEvent(MotionEvent event) {
    int x = (int) event.getX();
    int y = (int) event.getY();

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            sigPoints.add(new LinePathPoint(x, y, LinePathPoint.TYPE_LINE_START));

            if (sigPath.isEmpty()) {
                callbacks.onSignatureStarted();
            }

            sigPath.moveTo(x, y);

            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
        case MotionEvent.ACTION_UP:

            int hSize = event.getHistorySize();

            for (int i = 0; i < hSize; i++) {
                int hX = (int) event.getHistoricalX(i);
                int hY = (int) event.getHistoricalY(i);
                sigPath.lineTo(hX, hY);
                sigPoints.add(new LinePathPoint(x, y, LinePathPoint.TYPE_LINE_POINT));
            }

            sigPath.lineTo(x, y);
            sigPoints.add(new LinePathPoint(x, y, LinePathPoint.TYPE_LINE_POINT));

            invalidate();
            break;
    }

    return true;
}
 
public boolean init(View view, MotionEvent event) {

            // We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
            // we declare the event 'invalid' and expect it in consequent events.
            if (event.getHistorySize() == 0) {
                return false;
            }

            // Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
            final float dy = event.getY(0) - event.getHistoricalY(0, 0);
            final float dx = event.getX(0) - event.getHistoricalX(0, 0);
            if (Math.abs(dx) > Math.abs(dy)) {
                return false;
            }

            if( dy == 0.f  ) { // just click event
                return false;
            }

//            mAbsOffset = view.getTranslationY();
            mAbsOffset = getViewOffset(view);
            mDeltaOffset = dy;
            mDir = mDeltaOffset > 0;
            Log.d("wxy-motion", String.format("mAbsOffset %s mDeltaOffset %s", mAbsOffset, mDeltaOffset));
            Log.d("wxy-motion","mDir = " + mDir);
            return true;
        }
 
public boolean init(View view, MotionEvent event) {

            // We must have history available to calc the dx. Normally it's there - if it isn't temporarily,
            // we declare the event 'invalid' and expect it in consequent events.
            if (event.getHistorySize() == 0) {
                return false;
            }

            // Allow for counter-orientation-direction operations (e.g. item swiping) to run fluently.
            final float dx = event.getX(0) - event.getHistoricalX(0, 0);
            final float dy = event.getY(0) - event.getHistoricalY(0, 0);
            if (Math.abs(dx) < Math.abs(dy)) {
                return false;
            }

            if( dx == 0.f ) { // just click event
                return false;
            }

//            mAbsOffset = view.getTranslationX();
            mAbsOffset = getViewOffset(view);
            mDeltaOffset = dx;
            mDir = mDeltaOffset > 0;
            Log.d("wxy-motion", String.format("mAbsOffset %s mDeltaOffset %s", mAbsOffset, mDeltaOffset));
            Log.d("wxy-motion","mDir = " + mDir);
            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);

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

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

    // Act

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

    // Assert

    final float expectedTransX1 = (event1.getX() - event1.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
    final float expectedTransX2 = (event2.getX() - event2.getHistoricalX(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD;
    verify(mView).setTranslationX(expectedTransX2);
    verify(mView, never()).setTranslationY(anyFloat());
    assertTrue(ret);
    assertEquals(STATE_DRAG_END_SIDE, uut.getCurrentState());

    // State-change listener called only once?
    verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
    verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
    // Update-listener called exactly twice?
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransX1));
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransX2));
    verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
}
 
源代码7 项目: codeexamples-android   文件: SignatureView.java
@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:
		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;
}
 
源代码8 项目: MHViewer   文件: LockPatternView.java
private void handleActionMove(MotionEvent event) {
    // Handle all recent motion events so we don't skip any cells even when the device
    // is busy...
    final float radius = mPathWidth;
    final int historySize = event.getHistorySize();
    mTmpInvalidateRect.setEmpty();
    boolean invalidateNow = false;
    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();
        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 > DRAG_THRESHHOLD || dy > DRAG_THRESHHOLD) {
            invalidateNow = true;
        }

        if (mPatternInProgress && patternSize > 0) {
            final ArrayList<Cell> pattern = mPattern;
            final Cell lastCell = pattern.get(patternSize - 1);
            float lastCellCenterX = getCenterXForColumn(lastCell.column);
            float lastCellCenterY = getCenterYForRow(lastCell.row);

            // Adjust for drawn segment from last cell to (x,y). Radius accounts for line width.
            float left = Math.min(lastCellCenterX, x) - radius;
            float right = Math.max(lastCellCenterX, x) + radius;
            float top = Math.min(lastCellCenterY, y) - radius;
            float bottom = Math.max(lastCellCenterY, y) + radius;

            // Invalidate between the pattern's new cell and the pattern's previous cell
            if (hitCell != null) {
                final float width = mSquareWidth * 0.5f;
                final float height = mSquareHeight * 0.5f;
                final float hitCellCenterX = getCenterXForColumn(hitCell.column);
                final float hitCellCenterY = getCenterYForRow(hitCell.row);

                left = Math.min(hitCellCenterX - width, left);
                right = Math.max(hitCellCenterX + width, right);
                top = Math.min(hitCellCenterY - height, top);
                bottom = Math.max(hitCellCenterY + height, bottom);
            }

            // Invalidate between the pattern's last cell and the previous location
            mTmpInvalidateRect.union(Math.round(left), Math.round(top),
                    Math.round(right), Math.round(bottom));
        }
    }
    mInProgressX = event.getX();
    mInProgressY = event.getY();

    // To save updates, we only invalidate if the user moved beyond a certain amount.
    if (invalidateNow) {
        mInvalidate.union(mTmpInvalidateRect);
        invalidate(mInvalidate);
        mInvalidate.set(mTmpInvalidateRect);
    }
}
 
@Test
public void onTouchMoveAction_undragWhenUpOverscrolled_endOverscrolling() {

    // 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);

    VerticalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
    MotionEvent eventMoveUp = createLongUpwardsMoveEvent();
    uut.onTouch(mView, eventMoveUp);
    reset(mView);
    float startTransX = (eventMoveUp.getX() - eventMoveUp.getHistoricalX(0)) / touchDragRatioFwd;
    when(mView.getTranslationX()).thenReturn(startTransX);

    // Create the (negative) downwards-drag event
    MotionEvent eventMoveDown = createLongDownwardsMoveEvent();

    // Act

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

    // Assert

    verify(mView, never()).setTranslationX(anyFloat());
    verify(mView).setTranslationY(0);
    assertTrue(ret);
    assertEquals(STATE_IDLE, uut.getCurrentState());

    // State-change listener invoked to say drag-on and drag-off (idle).
    verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
    verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_DRAG_END_SIDE), eq(STATE_IDLE));
    verify(mStateListener, times(2)).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
    // Update-listener called exactly twice?
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(startTransX));
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(0f));
    verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
}
 
源代码10 项目: Backboard   文件: Actor.java
@Override
@SuppressLint("ClickableViewAccessibility")
public boolean onTouch(@NonNull final View v, @NonNull final MotionEvent event) {

	final boolean retVal;

	if (!mMotionListenerEnabled || mMotions.isEmpty()) {

		if (mOnTouchListener != null) {
			retVal = mOnTouchListener.onTouch(v, event);
		} else {
			retVal = false;
		}

		return retVal;
	}

	for (Motion motion : mMotions) {
		for (EventImitator imitator : motion.imitators) {
			imitator.imitate(v, event);
		}
	}

	if (mOnTouchListener != null) {
		retVal = mOnTouchListener.onTouch(v, event);
	} else {
		retVal = true;
	}

	if (mRequestDisallowTouchEvent) {
		// prevents parent from scrolling or otherwise stealing touch events
		v.getParent().requestDisallowInterceptTouchEvent(true);
	}

	if (v.isClickable()) {
		if (event.getEventTime() - event.getDownTime()
				> ViewConfiguration.getLongPressTimeout()) {
			v.setPressed(false);

			return true;
		}

		if (event.getHistorySize() > 0) {
			final float deltaX = event.getHistoricalX(event.getHistorySize() - 1) - event.getX();
			final float deltaY = event.getHistoricalY(event.getHistorySize() - 1) - event.getY();

			// if user has moved too far, it is no longer a click
			final boolean removeClickState = Math.pow(deltaX, 2) + Math.pow(deltaY, 2)
					> Math.pow(MAX_CLICK_DISTANCE, 2);

			v.setPressed(!removeClickState);

			return removeClickState;
		} else {
			return false;
		}
	}

	return retVal;
}
 
源代码11 项目: osmdroid   文件: MultiTouchController.java
/** Process incoming touch events */
@SuppressWarnings("unused")
public boolean onTouchEvent(MotionEvent event) {
	try {
		int pointerCount = multiTouchSupported ? (Integer) m_getPointerCount.invoke(event) : 1;
		if (DEBUG)
			Log.i("MultiTouch", "Got here 1 - " + multiTouchSupported + " " + mMode + " " + handleSingleTouchEvents + " " + pointerCount);
		if (mMode == MODE_NOTHING && !handleSingleTouchEvents && pointerCount == 1)
			// Not handling initial single touch events, just pass them on
			return false;
		if (DEBUG)
			Log.i("MultiTouch", "Got here 2");

		// Handle history first (we sometimes get history with ACTION_MOVE events)
		int action = event.getAction();
		int histLen = event.getHistorySize() / pointerCount;
		for (int histIdx = 0; histIdx <= histLen; histIdx++) {
			// Read from history entries until histIdx == histLen, then read from current event
			boolean processingHist = histIdx < histLen;
			if (!multiTouchSupported || pointerCount == 1) {
				// Use single-pointer methods -- these are needed as a special case (for some weird reason) even if
				// multitouch is supported but there's only one touch point down currently -- event.getX(0) etc. throw
				// an exception if there's only one point down.
				if (DEBUG)
					Log.i("MultiTouch", "Got here 3");
				xVals[0] = processingHist ? event.getHistoricalX(histIdx) : event.getX();
				yVals[0] = processingHist ? event.getHistoricalY(histIdx) : event.getY();
				pressureVals[0] = processingHist ? event.getHistoricalPressure(histIdx) : event.getPressure();
			} else {
				// Read x, y and pressure of each pointer
				if (DEBUG)
					Log.i("MultiTouch", "Got here 4");
				int numPointers = Math.min(pointerCount, MAX_TOUCH_POINTS);
				if (DEBUG && pointerCount > MAX_TOUCH_POINTS)
					Log.i("MultiTouch", "Got more pointers than MAX_TOUCH_POINTS");
				for (int ptrIdx = 0; ptrIdx < numPointers; ptrIdx++) {
					int ptrId = (Integer) m_getPointerId.invoke(event, ptrIdx);
					pointerIds[ptrIdx] = ptrId;
					// N.B. if pointerCount == 1, then the following methods throw an array index out of range exception,
					// and the code above is therefore required not just for Android 1.5/1.6 but also for when there is
					// only one touch point on the screen -- pointlessly inconsistent :(
					xVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalX.invoke(event, ptrIdx, histIdx) : m_getX.invoke(event, ptrIdx));
					yVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalY.invoke(event, ptrIdx, histIdx) : m_getY.invoke(event, ptrIdx));
					pressureVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalPressure.invoke(event, ptrIdx, histIdx) : m_getPressure
							.invoke(event, ptrIdx));
				}
			}
			// Decode event
			decodeTouchEvent(pointerCount, xVals, yVals, pressureVals, pointerIds, //
					/* action = */processingHist ? MotionEvent.ACTION_MOVE : action, //
					/* down = */processingHist ? true : action != MotionEvent.ACTION_UP //
							&& (action & ((1 << ACTION_POINTER_INDEX_SHIFT) - 1)) != ACTION_POINTER_UP //
							&& action != MotionEvent.ACTION_CANCEL, //
					processingHist ? event.getHistoricalEventTime(histIdx) : event.getEventTime());
		}

		return true;
	} catch (Exception e) {
		// In case any of the introspection stuff fails (it shouldn't)
		Log.e("MultiTouchController", "onTouchEvent() failed", e);
		return false;
	}
}
 
源代码12 项目: Androzic   文件: MultiTouchController.java
/** Process incoming touch events */
public boolean onTouchEvent(MotionEvent event) {
	try {
		int pointerCount = multiTouchSupported ? (Integer) m_getPointerCount.invoke(event) : 1;
		if (DEBUG)
			Log.i("MultiTouch", "Got here 1 - " + multiTouchSupported + " " + mMode + " " + handleSingleTouchEvents + " " + pointerCount);
		if (mMode == MODE_NOTHING && !handleSingleTouchEvents && pointerCount == 1)
			// Not handling initial single touch events, just pass them on
			return false;
		if (DEBUG)
			Log.i("MultiTouch", "Got here 2");

		// Handle history first (we sometimes get history with ACTION_MOVE events)
		int action = event.getAction();
		int histLen = event.getHistorySize() / pointerCount;
		for (int histIdx = 0; histIdx <= histLen; histIdx++) {
			// Read from history entries until histIdx == histLen, then read from current event
			boolean processingHist = histIdx < histLen;
			if (!multiTouchSupported || pointerCount == 1) {
				// Use single-pointer methods -- these are needed as a special case (for some weird reason) even if
				// multitouch is supported but there's only one touch point down currently -- event.getX(0) etc. throw
				// an exception if there's only one point down.
				if (DEBUG)
					Log.i("MultiTouch", "Got here 3");
				xVals[0] = processingHist ? event.getHistoricalX(histIdx) : event.getX();
				yVals[0] = processingHist ? event.getHistoricalY(histIdx) : event.getY();
				pressureVals[0] = processingHist ? event.getHistoricalPressure(histIdx) : event.getPressure();
			} else {
				// Read x, y and pressure of each pointer
				if (DEBUG)
					Log.i("MultiTouch", "Got here 4");
				int numPointers = Math.min(pointerCount, MAX_TOUCH_POINTS);
				if (DEBUG && pointerCount > MAX_TOUCH_POINTS)
					Log.i("MultiTouch", "Got more pointers than MAX_TOUCH_POINTS");
				for (int ptrIdx = 0; ptrIdx < numPointers; ptrIdx++) {
					int ptrId = (Integer) m_getPointerId.invoke(event, ptrIdx);
					pointerIds[ptrIdx] = ptrId;
					// N.B. if pointerCount == 1, then the following methods throw an array index out of range exception,
					// and the code above is therefore required not just for Android 1.5/1.6 but also for when there is
					// only one touch point on the screen -- pointlessly inconsistent :(
					xVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalX.invoke(event, ptrIdx, histIdx) : m_getX.invoke(event, ptrIdx));
					yVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalY.invoke(event, ptrIdx, histIdx) : m_getY.invoke(event, ptrIdx));
					pressureVals[ptrIdx] = (Float) (processingHist ? m_getHistoricalPressure.invoke(event, ptrIdx, histIdx) : m_getPressure
							.invoke(event, ptrIdx));
				}
			}
			// Decode event
			decodeTouchEvent(pointerCount, xVals, yVals, pressureVals, pointerIds, //
					/* action = */processingHist ? MotionEvent.ACTION_MOVE : action, //
					/* down = */processingHist ? true : action != MotionEvent.ACTION_UP //
							&& (action & ((1 << ACTION_POINTER_INDEX_SHIFT) - 1)) != ACTION_POINTER_UP //
							&& action != MotionEvent.ACTION_CANCEL, //
					processingHist ? event.getHistoricalEventTime(histIdx) : event.getEventTime());
		}

		return true;
	} catch (Exception e) {
		// In case any of the introspection stuff fails (it shouldn't)
		Log.e("MultiTouchController", "onTouchEvent() failed", e);
		return false;
	}
}
 
源代码13 项目: deltachat-android   文件: ImageEditorView.java
private static PointF getHistoricalPoint(MotionEvent event, int p, int historicalIndex) {
  return new PointF(event.getHistoricalX(p, historicalIndex),
                    event.getHistoricalY(p, historicalIndex));
}
 
@Test
public void onTouchMoveAction_undragWhenRightOverscrolled_endOverscrolling() {

    // 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 right-overscroll state
    when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
    when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);

    HorizontalOverScrollBounceEffectDecorator uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
    MotionEvent eventMoveRight = createLongRightMoveEvent();
    uut.onTouch(mView, eventMoveRight);
    reset(mView);
    float startTransX = (eventMoveRight.getX() - eventMoveRight.getHistoricalX(0)) / touchDragRatioFwd;
    when(mView.getTranslationX()).thenReturn(startTransX);

    // Create the left-drag event
    MotionEvent eventMoveLeft = createLongLeftMoveEvent();

    // Act

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

    // Assert

    verify(mView).setTranslationX(0);
    verify(mView, never()).setTranslationY(anyFloat());
    assertTrue(ret);
    assertEquals(STATE_IDLE, uut.getCurrentState());

    // State-change listener invoked to say drag-on and drag-off (idle).
    verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
    verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_DRAG_START_SIDE), eq(STATE_IDLE));
    verify(mStateListener, times(2)).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
    // Update-listener called exactly twice?
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(startTransX));
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(0f));
    verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
}
 
源代码15 项目: xmpp   文件: LockPatternView.java
private void handleActionMove(MotionEvent event) {
    // Handle all recent motion events so we don't skip any cells even when the device
    // is busy...
    final float radius = (mSquareWidth * mDiameterFactor * 0.5f);
    final int historySize = event.getHistorySize();
    mTmpInvalidateRect.setEmpty();
    boolean invalidateNow = false;
    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();
        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 > DRAG_THRESHHOLD || dy > DRAG_THRESHHOLD) {
            invalidateNow = true;
        }

        if (mPatternInProgress && patternSize > 0) {
            final ArrayList<Cell> pattern = mPattern;
            final Cell lastCell = pattern.get(patternSize - 1);
            float lastCellCenterX = getCenterXForColumn(lastCell.column);
            float lastCellCenterY = getCenterYForRow(lastCell.row);

            // Adjust for drawn segment from last cell to (x,y). Radius accounts for line width.
            float left = Math.min(lastCellCenterX, x) - radius;
            float right = Math.max(lastCellCenterX, x) + radius;
            float top = Math.min(lastCellCenterY, y) - radius;
            float bottom = Math.max(lastCellCenterY, y) + radius;

            // Invalidate between the pattern's new cell and the pattern's previous cell
            if (hitCell != null) {
                final float width = mSquareWidth * 0.5f;
                final float height = mSquareHeight * 0.5f;
                final float hitCellCenterX = getCenterXForColumn(hitCell.column);
                final float hitCellCenterY = getCenterYForRow(hitCell.row);

                left = Math.min(hitCellCenterX - width, left);
                right = Math.max(hitCellCenterX + width, right);
                top = Math.min(hitCellCenterY - height, top);
                bottom = Math.max(hitCellCenterY + height, bottom);
            }

            // Invalidate between the pattern's last cell and the previous location
            mTmpInvalidateRect.union(Math.round(left), Math.round(top),
                    Math.round(right), Math.round(bottom));
        }
    }
    mInProgressX = event.getX();
    mInProgressY = event.getY();

    // To save updates, we only invalidate if the user moved beyond a certain amount.
    if (invalidateNow) {
        mInvalidate.union(mTmpInvalidateRect);
        invalidate(mInvalidate);
        mInvalidate.set(mTmpInvalidateRect);
    }
}
 
源代码16 项目: android-lockpattern   文件: LockPatternView.java
private void handleActionMove(MotionEvent event) {
    // Handle all recent motion events so we don't skip any cells even when
    // the device
    // is busy...
    final float radius = mPathWidth;
    final int historySize = event.getHistorySize();
    mTmpInvalidateRect.setEmpty();
    boolean invalidateNow = false;
    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();
        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 > DRAG_THRESHHOLD || dy > DRAG_THRESHHOLD) {
            invalidateNow = true;
        }

        if (mPatternInProgress && patternSize > 0) {
            final ArrayList<Cell> pattern = mPattern;
            final Cell lastCell = pattern.get(patternSize - 1);
            float lastCellCenterX = getCenterXForColumn(lastCell.column);
            float lastCellCenterY = getCenterYForRow(lastCell.row);

            // Adjust for drawn segment from last cell to (x,y). Radius
            // accounts for line width.
            float left = Math.min(lastCellCenterX, x) - radius;
            float right = Math.max(lastCellCenterX, x) + radius;
            float top = Math.min(lastCellCenterY, y) - radius;
            float bottom = Math.max(lastCellCenterY, y) + radius;

            // Invalidate between the pattern's new cell and the pattern's
            // previous cell
            if (hitCell != null) {
                final float width = mSquareWidth * 0.5f;
                final float height = mSquareHeight * 0.5f;
                final float hitCellCenterX = getCenterXForColumn(hitCell.column);
                final float hitCellCenterY = getCenterYForRow(hitCell.row);

                left = Math.min(hitCellCenterX - width, left);
                right = Math.max(hitCellCenterX + width, right);
                top = Math.min(hitCellCenterY - height, top);
                bottom = Math.max(hitCellCenterY + height, bottom);
            }

            // Invalidate between the pattern's last cell and the previous
            // location
            mTmpInvalidateRect.union(Math.round(left), Math.round(top),
                    Math.round(right), Math.round(bottom));
        }
    }
    mInProgressX = event.getX();
    mInProgressY = event.getY();

    // To save updates, we only invalidate if the user moved beyond a
    // certain amount.
    if (invalidateNow) {
        mInvalidate.union(mTmpInvalidateRect);
        invalidate(mInvalidate);
        mInvalidate.set(mTmpInvalidateRect);
    }
}
 
源代码17 项目: UltimateAndroid   文件: DrawableView.java
@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:
            Logs.d("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;
}
 
/**
 * When over-scroll has already started (to the right 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_dragLeftWhenRightOverscolled_continueOverscrollingLeft() 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 right-overscroll state
    when(mViewAdapter.isInAbsoluteStart()).thenReturn(true);
    when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false);

    HorizontalElasticityBounceEffect uut = getUUT(touchDragRatioFwd, touchDragRatioBck);
    MotionEvent eventMoveRight = createLongRightMoveEvent();
    uut.onTouch(mView, eventMoveRight);
    reset(mView);
    float startTransX = (eventMoveRight.getX() - eventMoveRight.getHistoricalX(0)) / touchDragRatioFwd;
    when(mView.getTranslationX()).thenReturn(startTransX);

    // Create the left-drag event
    MotionEvent eventMoveLeft = createShortLeftMoveEvent();

    // Act

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

    // Assert

    float expectedTransX = startTransX +
                            (eventMoveLeft.getX() - eventMoveLeft.getHistoricalX(0)) / touchDragRatioBck;
    verify(mView).setTranslationX(expectedTransX);
    verify(mView, never()).setTranslationY(anyFloat());
    assertTrue(ret);
    assertEquals(STATE_DRAG_START_SIDE, uut.getCurrentState());

    // State-change listener called only once?
    verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE));
    verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
    // Update-listener called exactly twice?
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(startTransX));
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransX));
    verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
}
 
/**
 * 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() {

    // 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);
    assertEquals(STATE_DRAG_END_SIDE, uut.getCurrentState());

    // State-change listener called only once?
    verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE));
    verify(mStateListener).onOverScrollStateChange(eq(uut), anyInt(), anyInt());
    // Update-listener called exactly twice?
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(startTransX));
    verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransX));
    verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat());
}
 
源代码20 项目: codeexamples-android   文件: SignatureView3Fast.java
@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:
      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;
}