/** * <i>Note that this method does not check the validity of</i> <code>index</code>. * * @param event * the event to inspect * @param index * the historical index (in {@link MotionEvent#getHistoricalX(int)} or {@link MotionEvent#getHistoricalY(int)}) * @return the historical value that this property represents on the given * <code>MotionEvent</code>. */ public float getHistoricalValue(@Nullable final MotionEvent event, final int index) { if (event != null) { switch (this) { case X: return event.getHistoricalX(index); case Y: return event.getHistoricalY(index); default: return 0; } } return 0; }
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; } mAbsOffset = view.getTranslationY(); mDeltaOffset = dy; mDir = mDeltaOffset > 0; 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; } mAbsOffset = view.getTranslationX(); mDeltaOffset = dx; mDir = mDeltaOffset > 0; return true; } }
protected MotionEvent createShortUpwardsMoveEvent() { MotionEvent event = mock(MotionEvent.class); when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE); when(event.getX()).thenReturn(200f); when(event.getY()).thenReturn(100f); when(event.getX(0)).thenReturn(200f); when(event.getY(0)).thenReturn(100f); when(event.getHistorySize()).thenReturn(1); when(event.getHistoricalX(eq(0))).thenReturn(220f); when(event.getHistoricalY(eq(0))).thenReturn(120f); when(event.getHistoricalX(eq(0), eq(0))).thenReturn(220f); when(event.getHistoricalY(eq(0), eq(0))).thenReturn(120f); return event; }
protected MotionEvent createLongRightMoveEvent() { MotionEvent event = mock(MotionEvent.class); when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE); when(event.getX()).thenReturn(150f); when(event.getY()).thenReturn(250f); when(event.getX(0)).thenReturn(150f); when(event.getY(0)).thenReturn(250f); 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; }
protected MotionEvent createShortLeftMoveEvent() { MotionEvent event = mock(MotionEvent.class); when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE); when(event.getX()).thenReturn(100f); when(event.getY()).thenReturn(200f); when(event.getX(0)).thenReturn(100f); when(event.getY(0)).thenReturn(200f); when(event.getHistorySize()).thenReturn(1); when(event.getHistoricalX(eq(0))).thenReturn(120f); when(event.getHistoricalY(eq(0))).thenReturn(220f); when(event.getHistoricalX(eq(0), eq(0))).thenReturn(120f); when(event.getHistoricalY(eq(0), eq(0))).thenReturn(220f); return event; }
protected MotionEvent createLongDownwardsMoveEvent() { MotionEvent event = mock(MotionEvent.class); when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE); when(event.getX()).thenReturn(250f); when(event.getY()).thenReturn(150f); when(event.getX(0)).thenReturn(250f); when(event.getY(0)).thenReturn(150f); when(event.getHistorySize()).thenReturn(1); when(event.getHistoricalX(eq(0))).thenReturn(200f); when(event.getHistoricalY(eq(0))).thenReturn(100f); when(event.getHistoricalX(eq(0), eq(0))).thenReturn(200f); when(event.getHistoricalY(eq(0), eq(0))).thenReturn(100f); return event; }
protected MotionEvent createShortDownwardsMoveEvent() { MotionEvent event = mock(MotionEvent.class); when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE); when(event.getX()).thenReturn(200f); when(event.getY()).thenReturn(100f); when(event.getX(0)).thenReturn(200f); when(event.getY(0)).thenReturn(100f); when(event.getHistorySize()).thenReturn(1); when(event.getHistoricalX(eq(0))).thenReturn(190f); when(event.getHistoricalY(eq(0))).thenReturn(80f); when(event.getHistoricalX(eq(0), eq(0))).thenReturn(190f); when(event.getHistoricalY(eq(0), eq(0))).thenReturn(80f); return event; }
protected MotionEvent createLongUpwardsMoveEvent() { MotionEvent event = mock(MotionEvent.class); when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE); when(event.getX()).thenReturn(200f); when(event.getY()).thenReturn(100f); when(event.getX(0)).thenReturn(200f); when(event.getY(0)).thenReturn(100f); when(event.getHistorySize()).thenReturn(1); when(event.getHistoricalX(eq(0))).thenReturn(250f); when(event.getHistoricalY(eq(0))).thenReturn(150f); when(event.getHistoricalX(eq(0), eq(0))).thenReturn(250f); when(event.getHistoricalY(eq(0), eq(0))).thenReturn(150f); return event; }
protected MotionEvent createShortRightMoveEvent() { MotionEvent event = mock(MotionEvent.class); when(event.getAction()).thenReturn(MotionEvent.ACTION_MOVE); when(event.getX()).thenReturn(100f); when(event.getY()).thenReturn(200f); when(event.getX(0)).thenReturn(100f); when(event.getY(0)).thenReturn(200f); when(event.getHistorySize()).thenReturn(1); when(event.getHistoricalX(eq(0))).thenReturn(80f); when(event.getHistoricalY(eq(0))).thenReturn(190f); when(event.getHistoricalX(eq(0), eq(0))).thenReturn(80f); when(event.getHistoricalY(eq(0), eq(0))).thenReturn(190f); return event; }
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; }
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();
final float deltaY = event.getHistoricalY(event.getHistorySize() - 1) - event.getY();
@Test public void onTouchMoveAction_dragDownInUpperEnd_overscrollDownwards() throws Exception { // Arrange MotionEvent event = createShortDownwardsMoveEvent(); when(mViewAdapter.isInAbsoluteStart()).thenReturn(true); when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false); VerticalOverScrollBounceEffectDecorator uut = getUUT(); // Act boolean ret = uut.onTouch(mView, event); // Assert float expectedTransY = (event.getY() - event.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD; verify(mView).setTranslationY(expectedTransY); verify(mView, never()).setTranslationX(anyFloat()); assertTrue(ret); assertEquals(STATE_DRAG_START_SIDE, uut.getCurrentState()); verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_START_SIDE)); verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransY)); }
@Test public void onTouchMoveAction_dragUpInBottomEnd_overscrollUpwards() throws Exception { // Arrange MotionEvent event = createShortUpwardsMoveEvent(); when(mViewAdapter.isInAbsoluteStart()).thenReturn(false); when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true); VerticalOverScrollBounceEffectDecorator uut = getUUT(); // Act boolean ret = uut.onTouch(mView, event); // Assert float expectedTransY = (event.getY() - event.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD; verify(mView).setTranslationY(expectedTransY); verify(mView, never()).setTranslationX(anyFloat()); assertTrue(ret); assertEquals(STATE_DRAG_END_SIDE, uut.getCurrentState()); verify(mStateListener).onOverScrollStateChange(eq(uut), eq(STATE_IDLE), eq(STATE_DRAG_END_SIDE)); verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransY)); }
@Test public void onTouchMoveAction_2ndDownDragInUpperEnd_overscrollDownwardsFurther() throws Exception { // Arrange // Bring UUT to a downwards-overscroll state MotionEvent event1 = createShortDownwardsMoveEvent(); when(mViewAdapter.isInAbsoluteStart()).thenReturn(true); when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false); VerticalOverScrollBounceEffectDecorator uut = getUUT(); uut.onTouch(mView, event1); reset(mView); // Create 2nd downwards-drag event MotionEvent event2 = createLongDownwardsMoveEvent(); // Act final boolean ret = uut.onTouch(mView, event2); // Assert final float expectedTransY1 = (event1.getY() - event1.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD; final float expectedTransY2 = (event2.getY() - event2.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD; verify(mView).setTranslationY(expectedTransY2); verify(mView, never()).setTranslationX(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(expectedTransY1)); verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_START_SIDE), eq(expectedTransY2)); verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat()); }
@Test public void onTouchMoveAction_2ndUpDragInBottomEnd_overscrollUpwardsFurther() throws Exception { // Arrange // Bring UUT to an upwards-overscroll state MotionEvent event1 = createShortUpwardsMoveEvent(); when(mViewAdapter.isInAbsoluteStart()).thenReturn(false); when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true); VerticalOverScrollBounceEffectDecorator uut = getUUT(); uut.onTouch(mView, event1); reset(mView); // Create 2nd upward-drag event MotionEvent event2 = createLongUpwardsMoveEvent(); // Act final boolean ret = uut.onTouch(mView, event2); // Assert final float expectedTransY1 = (event1.getY() - event1.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD; final float expectedTransY2 = (event2.getY() - event2.getHistoricalY(0)) / DEFAULT_TOUCH_DRAG_MOVE_RATIO_FWD; verify(mView).setTranslationY(expectedTransY2); verify(mView, never()).setTranslationX(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(expectedTransY1)); verify(mUpdateListener).onOverScrollUpdate(eq(uut), eq(STATE_DRAG_END_SIDE), eq(expectedTransY2)); verify(mUpdateListener, times(2)).onOverScrollUpdate(eq(uut), anyInt(), anyFloat()); }
reset(mView); float startTransY = (eventMoveUp.getY() - eventMoveUp.getHistoricalY(0)) / touchDragRatioFwd; when(mView.getTranslationY()).thenReturn(startTransY); float expectedTransY = startTransY + (eventMoveDown.getY() - eventMoveDown.getHistoricalY(0)) / touchDragRatioBck; verify(mView).setTranslationY(expectedTransY); verify(mView, never()).setTranslationX(anyFloat());
if (mCurrentlyDrawing) { for (int i = 0; i < event.getHistorySize(); i++) { drawAlong(event.getHistoricalX(i), event.getHistoricalY(i));
uut.onTouch(mView, eventMoveRight); reset(mView); float startTransY = (eventMoveRight.getY() - eventMoveRight.getHistoricalY(0)) / touchDragRatioFwd; when(mView.getTranslationY()).thenReturn(startTransY); (eventMoveUpwards.getY() - eventMoveUpwards.getHistoricalY(0)) / touchDragRatioBck; verify(mView).setTranslationY(expectedTransY); verify(mView, never()).setTranslationX(anyFloat());