Espresso NestedScrollView

后端 未结 3 1879
不思量自难忘°
不思量自难忘° 2021-01-11 18:41

I am trying to test EditTexts in my form that are within a NestedScrollView. I am running the following code:

onView(withId(R.id.register_scroll_view)).perf         


        
相关标签:
3条回答
  • 2021-01-11 19:03

    Use

    onView(withId(R.id.register_scroll_view))
            .perform(swipeUp(), click())
    
    0 讨论(0)
  • 2021-01-11 19:11

    I have written single ViewAction for handling scroll to views that are children of NestedScrollView. It also takes into account that CoordinatorLayout might be a root - so you don't need to be afraid of toolbar changing it's size.

    There is some code. You need to copy paste this class to your project somewhere. And then you can use it for example like that:

    onView(withId(R.id.register_scroll_view))
            .perform(CustomScrollActions.nestedScrollTo, click());
    

    Important: it is not a replacement for scrollTo() it is another scrolling ViewAction that you should use instead in cases when you deal with NestedScrollView.

    So there is a ViewAction I was talking about:

    public class CustomScrollActions {
    
        public static ViewAction nestedScrollTo() {
            return new ViewAction() {
    
                @Override
                public Matcher<View> getConstraints() {
                    return Matchers.allOf(
                            isDescendantOfA(isAssignableFrom(NestedScrollView.class)),
                            withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE));
                }
    
                @Override
                public String getDescription() {
                    return "Find parent with type " + NestedScrollView.class +
                            " of matched view and programmatically scroll to it.";
                }
    
                @Override
                public void perform(UiController uiController, View view) {
                    try {
                        NestedScrollView nestedScrollView = (NestedScrollView)
                                findFirstParentLayoutOfClass(view, NestedScrollView.class);
                        if (nestedScrollView != null) {
                            CoordinatorLayout coordinatorLayout =
                                    (CoordinatorLayout) findFirstParentLayoutOfClass(view, CoordinatorLayout.class);
                            if (coordinatorLayout != null) {
                                CollapsingToolbarLayout collapsingToolbarLayout =
                                        findCollapsingToolbarLayoutChildIn(coordinatorLayout);
                                if (collapsingToolbarLayout != null) {
                                    int toolbarHeight = collapsingToolbarLayout.getHeight();
                                    nestedScrollView.startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
                                    nestedScrollView.dispatchNestedPreScroll(0, toolbarHeight, null, null);
                                }
                            }
                            nestedScrollView.scrollTo(0, view.getTop());
                        } else {
                            throw new Exception("Unable to find NestedScrollView parent.");
                        }
                    } catch (Exception e) {
                        throw new PerformException.Builder()
                                .withActionDescription(this.getDescription())
                                .withViewDescription(HumanReadables.describe(view))
                                .withCause(e)
                                .build();
                    }
                    uiController.loopMainThreadUntilIdle();
                }
            };
        }
    
        private static CollapsingToolbarLayout findCollapsingToolbarLayoutChildIn(ViewGroup viewGroup) {
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                View child = viewGroup.getChildAt(i);
                if (child instanceof CollapsingToolbarLayout) {
                    return (CollapsingToolbarLayout) child;
                } else if (child instanceof ViewGroup) {
                    return findCollapsingToolbarLayoutChildIn((ViewGroup) child);
                }
            }
            return null;
        }
    
        private static View findFirstParentLayoutOfClass(View view, Class<? extends View> parentClass) {
            ViewParent parent = new FrameLayout(view.getContext());
            ViewParent incrementView = null;
            int i = 0;
            while (parent != null && !(parent.getClass() == parentClass)) {
                if (i == 0) {
                    parent = findParent(view);
                } else {
                    parent = findParent(incrementView);
                }
                incrementView = parent;
                i++;
            }
            return (View) parent;
        }
    
        private static ViewParent findParent(View view) {
            return view.getParent();
        }
    
        private static ViewParent findParent(ViewParent view) {
            return view.getParent();
        }
    }
    
    0 讨论(0)
  • 2021-01-11 19:23

    I don't have any experience with NestedScrollView, but it appears that requestRectangleOnScreen(), which is how espresso scrolls in the regular ScrollView, should work with NestedScrollView just the same.

    The only problem is that ScrollView constrain is hardcoded into the scrollTo() action and NestedScrollView doesn't inherit the regular ScrollView.

    I believe the only solution here is to copy and paste entire ScrollToAction class into your own implementation of this action and replace the pesky constrain.

    0 讨论(0)
提交回复
热议问题