1c587f7dba5a337169e854e235da59f595255d6ccAga Madurska/*
2c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * Copyright (C) 2016 The Android Open Source Project
3c587f7dba5a337169e854e235da59f595255d6ccAga Madurska *
4c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * Licensed under the Apache License, Version 2.0 (the "License");
5c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * you may not use this file except in compliance with the License.
6c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * You may obtain a copy of the License at
7c587f7dba5a337169e854e235da59f595255d6ccAga Madurska *
8c587f7dba5a337169e854e235da59f595255d6ccAga Madurska *      http://www.apache.org/licenses/LICENSE-2.0
9c587f7dba5a337169e854e235da59f595255d6ccAga Madurska *
10c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * Unless required by applicable law or agreed to in writing, software
11c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * distributed under the License is distributed on an "AS IS" BASIS,
12c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * See the License for the specific language governing permissions and
14c587f7dba5a337169e854e235da59f595255d6ccAga Madurska * limitations under the License.
15c587f7dba5a337169e854e235da59f595255d6ccAga Madurska */
16c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
17c587f7dba5a337169e854e235da59f595255d6ccAga Madurskapackage android.support.v7.widget;
18c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
19c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport android.support.annotation.Nullable;
20c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport android.test.suitebuilder.annotation.MediumTest;
21c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport android.view.View;
22c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
23c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport org.junit.Test;
24c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport org.junit.runner.RunWith;
25c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport org.junit.runners.Parameterized;
26c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
27c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport java.util.ArrayList;
28c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport java.util.List;
29c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport java.util.concurrent.atomic.AtomicBoolean;
30c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
31c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport static junit.framework.Assert.assertEquals;
32c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport static junit.framework.Assert.assertNotSame;
33c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport static junit.framework.Assert.assertSame;
34c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport static junit.framework.Assert.assertTrue;
35c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
36c587f7dba5a337169e854e235da59f595255d6ccAga Madurska@RunWith(Parameterized.class)
37c587f7dba5a337169e854e235da59f595255d6ccAga Madurskapublic class GridLayoutManagerSnappingTest extends BaseGridLayoutManagerTest {
38c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
39c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    final Config mConfig;
40c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    final boolean mReverseScroll;
41c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
42c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    public GridLayoutManagerSnappingTest(Config config, boolean reverseScroll) {
43c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mConfig = config;
44c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mReverseScroll = reverseScroll;
45c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
46c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
47c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    @Parameterized.Parameters(name = "config:{0}, reverseScroll:{1}")
48c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    public static List<Object[]> getParams() {
49c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        List<Object[]> result = new ArrayList<>();
50c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        List<Config> configs = createBaseVariations();
51c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        for (Config config : configs) {
52c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            for (boolean reverseScroll : new boolean[] {true, false}) {
53c587f7dba5a337169e854e235da59f595255d6ccAga Madurska                result.add(new Object[]{config, reverseScroll});
54c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            }
55c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        }
56c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        return result;
57c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
58c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
59c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    @MediumTest
60c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    @Test
61c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    public void snapOnScrollSameView() throws Throwable {
62c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        final Config config = (Config) mConfig.clone();
63c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        RecyclerView recyclerView = setupBasic(config);
64c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        waitForFirstLayout(recyclerView);
65c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        setupSnapHelper();
66c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
67c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        // Record the current center view.
68c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        View view = findCenterView(mGlm);
69c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertCenterAligned(view);
70c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        int scrollDistance = (getViewDimension(view) / 2) - 1;
71c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        int scrollDist = mReverseScroll ? -scrollDistance : scrollDistance;
72c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.expectIdleState(2);
73c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        smoothScrollBy(scrollDist);
74c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.waitForSnap(10);
75c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
76c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        // Views have not changed
77c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        View viewAfterFling = findCenterView(mGlm);
78c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertSame("The view should have scrolled", view, viewAfterFling);
79c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertCenterAligned(viewAfterFling);
80c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
81c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
82c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    @Test
83c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    public void snapOnScrollNextItem() throws Throwable {
84c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        final Config config = (Config) mConfig.clone();
85c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        RecyclerView recyclerView = setupBasic(config);
86c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        waitForFirstLayout(recyclerView);
87c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        setupSnapHelper();
88c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
89c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        // Record the current center view.
90c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        View view = findCenterView(mGlm);
91c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertCenterAligned(view);
92c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        int scrollDistance = getViewDimension(view) + 1;
93c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        int scrollDist = mReverseScroll ? -scrollDistance : scrollDistance;
94c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
95c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        smoothScrollBy(scrollDist);
96c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        waitForIdleScroll(mRecyclerView);
97c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        waitForIdleScroll(mRecyclerView);
98c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
99c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        View viewAfterScroll = findCenterView(mGlm);
100c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
101c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertNotSame("The view should have scrolled", view, viewAfterScroll);
102c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertCenterAligned(viewAfterScroll);
103c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
104c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
105c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    @MediumTest
106c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    @Test
107c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    public void snapOnFlingSameView() throws Throwable {
108c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        final Config config = (Config) mConfig.clone();
109c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        RecyclerView recyclerView = setupBasic(config);
110c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        waitForFirstLayout(recyclerView);
111c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        setupSnapHelper();
112c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
113c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        // Record the current center view.
114c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        View view = findCenterView(mGlm);
115c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertCenterAligned(view);
116c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
117c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        // Velocity small enough to not scroll to the next view.
118c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        int velocity = (int) (1.000001 * mRecyclerView.getMinFlingVelocity());
119c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        int velocityDir = mReverseScroll ? -velocity : velocity;
120c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.expectIdleState(2);
121c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertTrue(fling(velocityDir, velocityDir));
122c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        // Wait for two settling scrolls: the initial one and the corrective one.
123c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        waitForIdleScroll(mRecyclerView);
124c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.waitForSnap(100);
125c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
126c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        View viewAfterFling = findCenterView(mGlm);
127c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
128c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertSame("The view should NOT have scrolled", view, viewAfterFling);
129c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertCenterAligned(viewAfterFling);
130c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
131c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
132c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
133c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    @MediumTest
134c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    @Test
135c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    public void snapOnFlingNextView() throws Throwable {
136c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        final Config config = (Config) mConfig.clone();
137c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        RecyclerView recyclerView = setupBasic(config);
138c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        waitForFirstLayout(recyclerView);
139c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        setupSnapHelper();
140c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
141c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        // Record the current center view.
142c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        View view = findCenterView(mGlm);
143c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertCenterAligned(view);
144c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
145c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        // Velocity high enough to scroll beyond the current view.
146c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        int velocity = (int) (0.2 * mRecyclerView.getMaxFlingVelocity());
147c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        int velocityDir = mReverseScroll ? -velocity : velocity;
148c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
149c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.expectIdleState(1);
150c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertTrue(fling(velocityDir, velocityDir));
151c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.waitForSnap(100);
152c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        getInstrumentation().waitForIdleSync();
153c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
154c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        View viewAfterFling = findCenterView(mGlm);
155c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
156c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertNotSame("The view should have scrolled", view, viewAfterFling);
157c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        assertCenterAligned(viewAfterFling);
158c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
159c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
160c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    private void setupSnapHelper() throws Throwable {
161c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        SnapHelper snapHelper = new LinearSnapHelper();
162c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.expectIdleState(1);
163c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        snapHelper.attachToRecyclerView(mRecyclerView);
164c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.waitForSnap(10);
165c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
166c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.expectLayout(1);
167c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        scrollToPosition(mConfig.mItemCount / 2);
168c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.waitForLayout(2);
169c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
170c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        View view = findCenterView(mGlm);
1713911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska        int scrollDistance = distFromCenter(view) / 2;
1723911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska        if (scrollDistance == 0) {
1733911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska            return;
1743911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska        }
1753911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska
176c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        int scrollDist = mReverseScroll ? -scrollDistance : scrollDistance;
177c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
178c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.expectIdleState(2);
179c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        smoothScrollBy(scrollDist);
180c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        mGlm.waitForSnap(10);
181c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
182c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
183c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    @Nullable View findCenterView(RecyclerView.LayoutManager layoutManager) {
184c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        if (layoutManager.canScrollHorizontally()) {
185c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            return mRecyclerView.findChildViewUnder(mRecyclerView.getWidth() / 2, 0);
186c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        } else {
187c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            return mRecyclerView.findChildViewUnder(0, mRecyclerView.getHeight() / 2);
188c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        }
189c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
190c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
191c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    private int getViewDimension(View view) {
192c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        OrientationHelper helper;
193c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        if (mGlm.canScrollHorizontally()) {
194c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            helper = OrientationHelper.createHorizontalHelper(mGlm);
195c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        } else {
196c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            helper = OrientationHelper.createVerticalHelper(mGlm);
197c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        }
198c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        return helper.getDecoratedMeasurement(view);
199c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
200c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
201c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    private void assertCenterAligned(View view) {
202c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        if(mGlm.canScrollHorizontally()) {
203c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            assertEquals("The child should align with the center of the parent",
204c587f7dba5a337169e854e235da59f595255d6ccAga Madurska                    mRecyclerView.getWidth() / 2,
205c587f7dba5a337169e854e235da59f595255d6ccAga Madurska                    mGlm.getDecoratedLeft(view) +
206c587f7dba5a337169e854e235da59f595255d6ccAga Madurska                            mGlm.getDecoratedMeasuredWidth(view) / 2);
207c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        } else {
208c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            assertEquals("The child should align with the center of the parent",
209c587f7dba5a337169e854e235da59f595255d6ccAga Madurska                    mRecyclerView.getHeight() / 2,
210c587f7dba5a337169e854e235da59f595255d6ccAga Madurska                    mGlm.getDecoratedTop(view) +
211c587f7dba5a337169e854e235da59f595255d6ccAga Madurska                            mGlm.getDecoratedMeasuredHeight(view) / 2);
212c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        }
213c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
214c587f7dba5a337169e854e235da59f595255d6ccAga Madurska
2153911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska    private int distFromCenter(View view) {
2163911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska        if (mGlm.canScrollHorizontally()) {
2173911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska            return Math.abs(mRecyclerView.getWidth() / 2 - mGlm.getViewBounds(view).centerX());
2183911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska        } else {
2193911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska            return Math.abs(mRecyclerView.getHeight() / 2 - mGlm.getViewBounds(view).centerY());
2203911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska        }
2213911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska    }
2223911e1c2d38e301d5ffbdf11f808fdc593dd83e9Aga Madurska
223c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    private boolean fling(final int velocityX, final int velocityY)
224c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            throws Throwable {
225c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        final AtomicBoolean didStart = new AtomicBoolean(false);
226c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        runTestOnUiThread(new Runnable() {
227c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            @Override
228c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            public void run() {
229c587f7dba5a337169e854e235da59f595255d6ccAga Madurska                boolean result = mRecyclerView.fling(velocityX, velocityY);
230c587f7dba5a337169e854e235da59f595255d6ccAga Madurska                didStart.set(result);
231c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            }
232c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        });
233c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        if (!didStart.get()) {
234c587f7dba5a337169e854e235da59f595255d6ccAga Madurska            return false;
235c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        }
236c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        waitForIdleScroll(mRecyclerView);
237c587f7dba5a337169e854e235da59f595255d6ccAga Madurska        return true;
238c587f7dba5a337169e854e235da59f595255d6ccAga Madurska    }
239c587f7dba5a337169e854e235da59f595255d6ccAga Madurska}
240