EDIT: Someone mentioned in the comments that withParentIndex is now available, give that a try first before using the custom solution below.
I was amazed that I couldn’t find a solution by simply providing an index along with a matcher (i.e. withText, withId). The accepted answer only solves the problem when you’re dealing with onData and ListViews.
If you have more than one view on the screen with the same resId/text/contentDesc, you can choose which one you want without causing an AmbiguousViewMatcherException by using this custom matcher:
public static Matcher<View> withIndex(final Matcher<View> matcher, final int index) {
return new TypeSafeMatcher<View>() {
int currentIndex = 0;
@Override
public void describeTo(Description description) {
description.appendText("with index: ");
description.appendValue(index);
matcher.describeTo(description);
}
@Override
public boolean matchesSafely(View view) {
return matcher.matches(view) && currentIndex++ == index;
}
};
}
For example:
onView(withIndex(withId(R.id.my_view), 2)).perform(click());
will perform a click action on the third instance of R.id.my_view.