Espresso:如何按索引滚动到 Horizo​​ntalScrollView 中的项目?

Espresso: How do I scroll to an item in a HorizontalScrollView by index?

这是我的 HorizontalScrollView 的样子:

<HorizontalScrollView
    android:layout_below="@id/saved_circuits_title"
    android:id="@+id/saved_circuits_scrollview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <LinearLayout
        android:id="@+id/saved_circuits_scroll"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:orientation="horizontal">
    </LinearLayout>
</HorizontalScrollView>

在我的 HomeActivity 中,我有以下相关代码用位图 HorizontalScrollView 填充

onCreate{
...
this.savedCircuitsScroll = (LinearLayout) findViewById(R.id.saved_circuits_scroll);
...
}

updateSavedCircuits(){
...// code to make an ImageView from a retrieved bitmap
newImageImage.setOnClickListener(this.thumbnailListener);
this.savedCircuitsScroll.addView(newImageImage);
...
}

如何使用 Espresso 滚动到 Horizo​​ntalScrollView 中指定索引处的 ImageView 并单击它?


我试过的

我的布局中没有 ID xml,因此 this 之类的方法不起作用:

onView( withId( R.id.button)).perform( scrollTo(), click());

我知道你可以 click on an item by index in a RecyclerView 并尝试为 HorizontalScrollViews:

寻找类似的方法
    onView(withId(R.id.saved_circuits_scroll))
            .perform(HorizontalScrollViewActions.actionOnItemAtPosition(0, click()));

除了 HorizontalScrollViewActions 不存在。

或以下 this blog 我尝试了以下操作以至少单击 HorizontalScrollView 中指定索引处的一个项目:

// Click item at position 3
onView(withHorizontalScrollView(R.id.scroll_view).atPosition(3)).perform(click());
// Convenience helper
public static HorizontalScrollViewMatcher withHorizontalScrollView(final int horizontalScrollViewId) {
    return new HorizontalScrollViewMatcher(horizontalScrollId);
}

除了 HorizontalScrollViewMatcher 不存在。

我们为HorizontalScrollView做什么?它不是 ScrollView 的后代,所以答案 here 建议我需要实现自己的自定义 ViewAction。我想要做的就是按索引滚动到 HorizontalScrollView 中的一个项目并单击它。这真的需要吗?如果这是我需要做的,我该如何实现这个自定义 ViewAction?


尝试添加这个匹配器。

public static Matcher<View> withIdAndParentId(final int viewId, final int parentId) {
    Assert.assertTrue(viewId != -1);
    Assert.assertTrue(parentId != -1);

    return new TypeSafeMatcher<View>() {

        @Override
        public void describeTo(Description description) {
        }

        @Override
        public boolean matchesSafely(View view) {
            return view.getId() == viewId && isThereParentWithIdInHierarchy(view);
        }

        private boolean isThereParentWithIdInHierarchy(View view) {
            ViewParent viewParent = view.getParent();
            if (viewParent == null || !(viewParent instanceof ViewGroup))
                return false;

            ViewGroup parent = (ViewGroup) viewParent;

            return parent.getId() == parentId || isThereParentWithIdInHierarchy(parent);
        }
    };
}

这是使用方法:

onView(withIdAndParentId(R.id.YOUR_PARTICULAR_VIEW_ID, R.id.horizontalScrollViewId)).perform(scrollTo(), click());

希望对你有帮助。

好的,所以在我的特殊情况下,我发现我的滚动视图没有与之关联的 ID(或者 none 我可以合理地达到,因此我不能使用 Mody 的答案)。但是,它们确实有一个与之关联的标签,因此我可以改用 Espresso 的 withTagValue ViewMatcher。每个视图都与一个 circuitProject 对象相关联(当然对您来说它可能不同)。我可以访问以下内容:

ArrayList<CircuitProject> circuitProjects = new ArrayList<>();

circuitProject 对象的索引恰好是 HorizontalScrollView 中关联视图的位置。标签是 circuitProject 对象保存到的文件夹。从这里可以直接获得我需要的 Espresso 滚动到 HorizontalScrollView:

中特定索引的行为
onView(withTagValue(withStringMatching(circuitProject.getFolderID()))).perform(scrollTo(), click());

在我的例子中,我通过使用得到它:

onView(allOf(withId(R.id.itemTextView), withEffectiveVisibility(Visibility.VISIBLE), withText(R.string.categories))).perform(scrollTo(), click())

R.id.itemTextView 是动态添加到 LinearLayout 的 TextView(带有文本 R.string.categories):

<HorizontalScrollView>
  <LinearLayout>
      ... [child added dynamically]
  </LinearLayout>
</HorizontalScrollView>