コンテンツに移動

よくアクセスするページ

最近アクセスしたページ

navigation

Espresso lists

Espresso offers mechanisms to scroll to or act on a particular item for two types of lists: adapter views and recycler views.

When dealing with lists, especially those created with a RecyclerView or an AdapterView object, the view that you’re interested in might not even be on the screen because only a small number of children are displayed and are recycled as you scroll. The scrollTo() method can’t be used in this case because it requires an existing view.

Interacting with adapter view list items

Instead of using the onView() method, start your search with onData() and provide a matcher against the data that is backing the view you’d like to match. Espresso will do all the work of finding the row in the Adapter object and making the item visible in the viewport.

Match data using a custom view matcher

The activity below contains a ListView, which is backed by a SimpleAdapter that holds data for each row in a Map<String, Object> object.

The list activity currently shown on the screen contains a list with
          23 items. Each item has a number, stored as a String, mapped to a
          different number, which is stored as an Object instead.

Each map has two entries: a key "STR" that contains a String, such as "item: x", and a key "LEN" that contains an Integer, which represents the length of the content. For example:

{"STR" : "item: 0", "LEN": 7}

The code for a click on the row with "item: 50" looks like this:

onData(allOf(is(instanceOf(Map.class)), hasEntry(equalTo("STR"), is("item: 50")))
    .perform(click());

Note that Espresso scrolls through the list automatically as needed.

Let’s take apart the Matcher<Object> inside onData(). The is(instanceOf(Map.class)) method narrows the search to any item of the AdapterView, which is backed by a Map object.

In our case, this aspect of the query matches every row of the list view, but we want to click specifically on an item, so we narrow the search further with:

hasEntry(equalTo("STR"), is("item: 50"))

This Matcher<String, Object> will match any Map that contains an entry with the key "STR" and the value "item: 50". Because the code to look up this is long and we want to reuse it in other locations, let’s write a custom withItemContent matcher for that:

return new BoundedMatcher<Object, Map>(Map.class) {
    @Override
    public boolean matchesSafely(Map map) {
        return hasEntry(equalTo("STR"), itemTextMatcher).matches(map);
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("with item content: ");
        itemTextMatcher.describeTo(description);
    }
};

You use a BoundedMatcher as a base because to only match objects of type Map. Override the matchesSafely() method, putting in the matcher found earlier, and match it against a Matcher<String> that you can pass as an argument. This allows you to call withItemContent(equalTo("foo")). For code brevity, you can create another matcher that already calls the equalTo() and accepts a String object:

public static Matcher<Object> withItemContent(String expectedText) {
    checkNotNull(expectedText);
    return withItemContent(equalTo(expectedText));
}

Now the code to click on the item is simple:

onData(withItemContent("item: 50")).perform(click());

For the full code of this test, take a look at the testClickOnItem50() method within the AdapterViewTest class and this custom LongListMatchers matcher.

Match a specific child view

The sample above issues a click in the middle of the entire row of a ListView. But what if we want to operate on a specific child of the row? For example, we would like to click on the second column of the row of the LongListActivity, which displays the String.length of the content in the first column:

In this example, it would be beneficial to extract just the length of
          a particular piece of content. This process involves determining the
          value of the second column in a row.

Just add an onChildView() specification to your implementation of DataInteraction:

onData(withItemContent("item: 60"))
    .onChildView(withId(R.id.item_size))
    .perform(click());

Interacting with recycler view list items

RecyclerView objects work differently than AdapterView objects, so onData() cannot be used to interact with them.

To interact with RecyclerViews using Espresso, you can use the espresso-contrib package, which has a collection of RecyclerViewActions that can be used to scroll to positions or to perform actions on items:

The following snippets feature some examples from the RecyclerViewSample sample:

@Test
public void scrollToItemBelowFold_checkItsText() {
    // First, scroll to the position that needs to be matched and click on it.
    onView(ViewMatchers.withId(R.id.recyclerView))
            .perform(RecyclerViewActions.actionOnItemAtPosition(ITEM_BELOW_THE_FOLD,
            click()));

    // Match the text in an item below the fold and check that it's displayed.
    String itemElementText = mActivityRule.getActivity().getResources()
            .getString(R.string.item_element_text)
            + String.valueOf(ITEM_BELOW_THE_FOLD);
    onView(withText(itemElementText)).check(matches(isDisplayed()));
}
@Test
public void itemInMiddleOfList_hasSpecialText() {
    // First, scroll to the view holder using the isInTheMiddle() matcher.
    onView(ViewMatchers.withId(R.id.recyclerView))
            .perform(RecyclerViewActions.scrollToHolder(isInTheMiddle()));

    // Check that the item has the special text.
    String middleElementText =
            mActivityRule.getActivity().getResources()
            .getString(R.string.middle);
    onView(withText(middleElementText)).check(matches(isDisplayed()));
}
このサイトでは、ユーザーが選択したサイトの言語と表示設定を保存する目的で Cookie を使用しています。

Android デベロッパー向けの最新情報やヒントを入手して、Google Play での成功を手に入れましょう。

* 必須

送信しました

WeChat で Google Developers をフォローする

このサイトをで表示しますか?

ページの表示言語としてを選択しましたが、このサイトの言語はに設定されています。

言語設定を変更してこのサイトをで表示しますか?言語設定を変更する場合は、各ページの下にある言語メニューを使用してください。

このクラスには、API レベル 以上が必要です。

API レベル が選択されているため、このドキュメントは非表示になっています。左のナビゲーションの上にあるセレクタを使って、ドキュメントの API レベルを変更できます。

アプリに必要な API レベルを指定する方法について、詳しくは異なるプラットフォーム バージョンのサポートをご覧ください。

Take a short survey?
Help us improve the Android developer experience. (April 2018 — Developer Survey)