public static IOverScrollDecor setUpOverScroll(ListView listView) { return new VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(listView)); }
protected VerticalOverScrollBounceEffectDecorator getUUT(float touchDragRatioFwd, float touchDragRatioBck) { VerticalOverScrollBounceEffectDecorator uut = new VerticalOverScrollBounceEffectDecorator(mViewAdapter, touchDragRatioFwd, touchDragRatioBck, DEFAULT_DECELERATE_FACTOR); uut.setOverScrollStateListener(mStateListener); uut.setOverScrollUpdateListener(mUpdateListener); return uut; } }
@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 detach_overScrollInEffect_detachFromView() throws Exception { when(mViewAdapter.isInAbsoluteStart()).thenReturn(true); when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false); VerticalOverScrollBounceEffectDecorator uut = getUUT(); uut.onTouch(mView, createShortDownwardsMoveEvent()); // Act uut.detach(); // Assert verify(mView).setOnTouchListener(eq((View.OnTouchListener) null)); verify(mView).setOverScrollMode(View.OVER_SCROLL_ALWAYS); }
@Test public void onTouchMoveAction_dragUpInUpperEnd_ignoreTouchEvent() throws Exception { // Arrange MotionEvent event = createShortUpwardsMoveEvent(); when(mViewAdapter.isInAbsoluteStart()).thenReturn(true); when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false); VerticalOverScrollBounceEffectDecorator uut = getUUT(); // Act boolean ret = uut.onTouch(mView, event); // Assert verify(mView, never()).setTranslationX(anyFloat()); verify(mView, never()).setTranslationY(anyFloat()); assertFalse(ret); assertEquals(STATE_IDLE, uut.getCurrentState()); verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt()); verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat()); }
public static IOverScrollDecor setUpOverScroll(GridView gridView) { return new VerticalOverScrollBounceEffectDecorator(new AbsListViewOverScrollDecorAdapter(gridView)); }
protected VerticalOverScrollBounceEffectDecorator getUUT() { VerticalOverScrollBounceEffectDecorator uut = new VerticalOverScrollBounceEffectDecorator(mViewAdapter); uut.setOverScrollStateListener(mStateListener); uut.setOverScrollUpdateListener(mUpdateListener); return uut; }
@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)); }
public static IOverScrollDecor setUpOverScroll(ScrollView scrollView) { return new VerticalOverScrollBounceEffectDecorator(new ScrollViewOverScrollDecorAdapter(scrollView)); }
@Test public void onTouchMoveAction_notInViewEnds_ignoreTouchEvent() throws Exception { // Arrange MotionEvent event = createShortDownwardsMoveEvent(); when(mViewAdapter.isInAbsoluteStart()).thenReturn(false); when(mViewAdapter.isInAbsoluteEnd()).thenReturn(false); VerticalOverScrollBounceEffectDecorator uut = getUUT(); // Act boolean ret = uut.onTouch(mView, event); // Assert verify(mView, never()).setTranslationX(anyFloat()); verify(mView, never()).setTranslationY(anyFloat()); assertFalse(ret); assertEquals(STATE_IDLE, uut.getCurrentState()); verify(mStateListener, never()).onOverScrollStateChange(eq(uut),anyInt(), anyInt()); verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat()); }
/** * Set up the over-scroll over a generic view, assumed to always be over-scroll ready (e.g. * a plain text field, image view). * * @param view The view. * @param orientation One of {@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL}. * * @return The over-scroll effect 'decorator', enabling further effect configuration. */ public static IOverScrollDecor setUpStaticOverScroll(View view, int orientation) { switch (orientation) { case ORIENTATION_HORIZONTAL: return new HorizontalOverScrollBounceEffectDecorator(new StaticOverScrollDecorAdapter(view)); case ORIENTATION_VERTICAL: return new VerticalOverScrollBounceEffectDecorator(new StaticOverScrollDecorAdapter(view)); default: throw new IllegalArgumentException("orientation"); } }
@Test public void onTouchMoveAction_dragDownInBottomEnd_ignoreTouchEvent() throws Exception { // Arrange MotionEvent event = createShortDownwardsMoveEvent(); when(mViewAdapter.isInAbsoluteStart()).thenReturn(false); when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true); VerticalOverScrollBounceEffectDecorator uut = getUUT(); // Act boolean ret = uut.onTouch(mView, event); // Assert verify(mView, never()).setTranslationX(anyFloat()); verify(mView, never()).setTranslationY(anyFloat()); assertFalse(ret); assertEquals(STATE_IDLE, uut.getCurrentState()); verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt()); verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat()); }
/** * Set up the over-scroll effect over a specified {@link RecyclerView} view. * <br/>Only recycler-views using <b>native</b> Android layout managers (i.e. {@link LinearLayoutManager}, * {@link GridLayoutManager} and {@link StaggeredGridLayoutManager}) are currently supported * by this convenience method. * * @param recyclerView The view. * @param orientation Either {@link #ORIENTATION_HORIZONTAL} or {@link #ORIENTATION_VERTICAL}. * * @return The over-scroll effect 'decorator', enabling further effect configuration. */ public static IOverScrollDecor setUpOverScroll(RecyclerView recyclerView, int orientation) { switch (orientation) { case ORIENTATION_HORIZONTAL: return new HorizontalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView)); case ORIENTATION_VERTICAL: return new VerticalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView)); default: throw new IllegalArgumentException("orientation"); } }
@Test public void onTouchUpAction_eventWhenNotOverscrolled_ignoreTouchEvent() throws Exception { // Arrange MotionEvent event = createDefaultUpActionEvent(); when(mViewAdapter.isInAbsoluteStart()).thenReturn(true); when(mViewAdapter.isInAbsoluteEnd()).thenReturn(true); VerticalOverScrollBounceEffectDecorator uut = getUUT(); // Act boolean ret = uut.onTouch(mView, event); // Assert verify(mView, never()).setTranslationX(anyFloat()); verify(mView, never()).setTranslationY(anyFloat()); assertFalse(ret); assertEquals(STATE_IDLE, uut.getCurrentState()); verify(mStateListener, never()).onOverScrollStateChange(eq(uut), anyInt(), anyInt()); verify(mUpdateListener, never()).onOverScrollUpdate(eq(uut), anyInt(), anyFloat()); }
mVertOverScrollEffect = new VerticalOverScrollBounceEffectDecorator(new RecyclerViewOverScrollDecorAdapter(recyclerView, itemTouchHelperCallback));
@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()); }
uut.onTouch(mView, eventMoveDown); reset(mView); float startTransX = (eventMoveDown.getX() - eventMoveDown.getHistoricalX(0)) / touchDragRatioFwd; boolean ret = uut.onTouch(mView, eventMoveUp); verify(mView).setTranslationY(0); assertTrue(ret); assertEquals(STATE_IDLE, uut.getCurrentState());
uut.onTouch(mView, eventMoveUp); reset(mView); float startTransX = (eventMoveUp.getX() - eventMoveUp.getHistoricalX(0)) / touchDragRatioFwd; boolean ret = uut.onTouch(mView, eventMoveDown); verify(mView).setTranslationY(0); assertTrue(ret); assertEquals(STATE_IDLE, uut.getCurrentState());
uut.onTouch(mView, eventMoveRight); reset(mView); float startTransY = (eventMoveRight.getY() - eventMoveRight.getHistoricalY(0)) / touchDragRatioFwd; boolean ret = uut.onTouch(mView, eventMoveUpwards); verify(mView, never()).setTranslationX(anyFloat()); assertTrue(ret); assertEquals(STATE_DRAG_START_SIDE, uut.getCurrentState());