Forked from miszmaniac/NestedScrollViewScrollToAction.java
Created
November 25, 2016 21:04
-
-
Save djodjoni/7c673a4e4ddc5c6ef4272ec7da15316a to your computer and use it in GitHub Desktop.
NestedScrollViewScrollToAction because regular ScrollTo doesn't work
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.NestedScrollViewScrollToAction; | |
import android.graphics.Rect; | |
import android.support.design.widget.CoordinatorLayout; | |
import android.support.test.espresso.PerformException; | |
import android.support.test.espresso.UiController; | |
import android.support.test.espresso.ViewAction; | |
import android.support.test.espresso.matcher.ViewMatchers.Visibility; | |
import android.support.test.espresso.util.HumanReadables; | |
import android.support.v4.widget.NestedScrollView; | |
import android.util.Log; | |
import android.view.View; | |
import org.hamcrest.Matcher; | |
import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom; | |
import static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA; | |
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayingAtLeast; | |
import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility; | |
import static org.hamcrest.Matchers.allOf; | |
import static org.hamcrest.Matchers.anyOf; | |
/** | |
* Enables scrolling to the given view. View must be a descendant of a ScrollView. | |
*/ | |
public final class NestedScrollViewScrollToAction implements ViewAction { | |
private static final String TAG = NestedScrollViewScrollToAction.class.getSimpleName(); | |
public static NestedScrollViewScrollToAction scrollTo() { | |
return new NestedScrollViewScrollToAction(); | |
} | |
@SuppressWarnings("unchecked") | |
@Override | |
public Matcher<View> getConstraints() { | |
return allOf(withEffectiveVisibility(Visibility.VISIBLE), isDescendantOfA(anyOf( | |
isAssignableFrom(NestedScrollView.class)))); | |
} | |
@Override | |
public void perform(UiController uiController, View view) { | |
if (isDisplayingAtLeast(90).matches(view)) { | |
Log.i(TAG, "View is already displayed. Returning."); | |
return; | |
} | |
View parentScrollView = findScrollView(view); | |
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) parentScrollView.getLayoutParams(); | |
params.setBehavior(null); | |
parentScrollView.requestLayout(); | |
uiController.loopMainThreadUntilIdle(); | |
Rect rect = new Rect(); | |
view.getDrawingRect(rect); | |
if (!view.requestRectangleOnScreen(rect, true /* immediate */)) { | |
Log.w(TAG, "Scrolling to view was requested, but none of the parents scrolled."); | |
} | |
uiController.loopMainThreadUntilIdle(); | |
if (!isDisplayingAtLeast(90).matches(view)) { | |
throw new PerformException.Builder() | |
.withActionDescription(this.getDescription()) | |
.withViewDescription(HumanReadables.describe(view)) | |
.withCause(new RuntimeException( | |
"Scrolling to view was attempted, but the view is not displayed")) | |
.build(); | |
} | |
} | |
private View findScrollView(View view) { | |
View parent = (View) view.getParent(); | |
if (parent != null) { | |
if (parent instanceof NestedScrollView) { | |
return parent; | |
} | |
return findScrollView(parent); | |
} | |
throw new PerformException.Builder() | |
.withActionDescription(this.getDescription()) | |
.withViewDescription(HumanReadables.describe(view)) | |
.withCause(new RuntimeException( | |
"Scrolling aborted due to not being NestedScrollView child")) | |
.build(); | |
} | |
@Override | |
public String getDescription() { | |
return "scroll to"; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment