The code onView( withId( R.id.button)).perform( scrollTo(), click());
will work if the view is descendant of ScrollView, HorizontalScrollView or ListView.
If we have NestedScrollView
instead of ScrollView
and for those who don't want to look into ScrollToAction
class code I wrote the sample.
As Bruno Oliveira said we can do something like this:
class ScrollToActionImproved : ViewAction {
override fun getConstraints(): Matcher<View> {
return allOf(
withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE),
isDescendantOfA(
anyOf(
isAssignableFrom(ScrollView::class.java),
isAssignableFrom(HorizontalScrollView::class.java),
isAssignableFrom(NestedScrollView::class.java)
)
)
)
}
override fun getDescription(): String = "scroll to view"
override fun perform(uiController: UiController?, view: View?) {
if (isDisplayingAtLeast(90).matches(view)) {
//View is already displayed
return
}
val rect = Rect()
view!!.getDrawingRect(rect)
if (!view.requestRectangleOnScreen(rect, true)) {
//Scrolling to view was requested, but none of the parents scrolled.
}
uiController!!.loopMainThreadUntilIdle()
if (!isDisplayingAtLeast(90).matches(view)) {
throw PerformException.Builder()
.withActionDescription(this.description)
.withViewDescription(HumanReadables.describe(view))
.withCause(
RuntimeException(
"Scrolling to view was attempted, but the view is not displayed"
)
)
.build()
}
}
}
And use it like this:
fun scrollToImproved(): ViewAction =
actionWithAssertions(ScrollToActionImproved())
/* some logic */
onView(withId(R.id.button)).perform(scrollToImproved())
It should work.