简体   繁体   中英

Clicking inside a Recycler view: Espresso

I am trying to click on a menu item inside Recycler view and I have following code.

onView(allOf(withId(R.id.section_list),isDisplayed())).perform(RecyclerViewActions.actionOnItem(hasDescendant(withText("ABC")), MyViewAction.clickChildViewWithId(R.id.payment_menu)));

and MyViewAction looks like this:

class MyViewAction {

public static ViewAction clickChildViewWithId(final int id) {
    return new ViewAction() {
        @Override
        public Matcher<View> getConstraints() {
            return null;
        }

        @Override
        public String getDescription() {
            return "Click on a child view with specified id.";
        }

        @Override
        public void perform(UiController uiController, View view) {
            View v = view.findViewById(id);
            v.performClick();
        }
    };
}
  • When I test it, I can see the Scrolling takes place to right position but the click fails with the following error

android.support.test.espresso.PerformException: Error performing 'android.support.test.espresso.contrib.RecyclerViewActions$ActionOnItemAtPositionViewAction@2fd64b56' on view 'with id: com.em3Agri.operation.debug:id/section_list'. at android.support.test.espresso.PerformException$Builder.build(PerformException.java:83) at ......... Caused by: java.lang.IllegalStateException: No view holder at position: 38 at android.support.test.espresso.contrib.RecyclerViewActions$ActionOnItemAtPositionViewAction.perform(RecyclerViewActions.java:290) at android.support.test.espresso.ViewInteraction$1.run(ViewInteraction.java:144)

I don't know if this is root cause of the error you're facing, but you should strictly adhere to the distinction between matcher and action , ie

RecyclerViewActions.actionOnItem(
    hasDescendant(withText("ABC")), 
    MyViewAction.clickChildViewWithId(R.id.payment_menu)
)

should rather be written as

RecyclerViewActions.actionOnItem(
    <something-that-selects-R.id.payment_menu-in-your-view-item>, 
    click()
)

What this something-that-selects-R.id.payment_menu-in-your-view-item actually is depends on your view's setup and might be hard to define properly, so maybe one of the other methods ( actionOnHolderItem eg) might be a better fit. This should also run faster, since it can directly jump to a view that was identified by a specific viewholder, whereas the Matcher<View> version can only "scroll" through your RecyclerView item by item and check every newly bound version.

How about:

onView(withId(R.id.section_list))
  .perform(
    RecyclerViewActions.actionOnItem(
      hasDescendant(withId(R.id.payment_menu)), 
      ViewActions.click()
    )
  ); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM