1c587f7dba5a337169e854e235da59f595255d6ccAga Madurska/* 2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 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 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.recyclerview.widget; 18c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 19fa39e2bca1b284ad7c931d9194287770b7b507faAurimas Liutikasimport static org.junit.Assert.assertEquals; 20fa39e2bca1b284ad7c931d9194287770b7b507faAurimas Liutikasimport static org.junit.Assert.assertNotSame; 21fa39e2bca1b284ad7c931d9194287770b7b507faAurimas Liutikasimport static org.junit.Assert.assertSame; 22fa39e2bca1b284ad7c931d9194287770b7b507faAurimas Liutikasimport static org.junit.Assert.assertTrue; 23e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas 2435232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikasimport android.support.test.filters.LargeTest; 25c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport android.view.View; 2624e2d006cef58a0e36a738e0a62a58d0f47e74b6Aga Madurskaimport android.widget.TextView; 27c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 28c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.annotation.Nullable; 29c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas 30c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport org.junit.Test; 31c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport org.junit.runner.RunWith; 32c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport org.junit.runners.Parameterized; 33c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 34c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport java.util.ArrayList; 35c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport java.util.List; 36c587f7dba5a337169e854e235da59f595255d6ccAga Madurskaimport java.util.concurrent.atomic.AtomicBoolean; 37c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 3835232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikas@LargeTest 39c587f7dba5a337169e854e235da59f595255d6ccAga Madurska@RunWith(Parameterized.class) 40c587f7dba5a337169e854e235da59f595255d6ccAga Madurskapublic class GridLayoutManagerSnappingTest extends BaseGridLayoutManagerTest { 41c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 42c587f7dba5a337169e854e235da59f595255d6ccAga Madurska final Config mConfig; 43c587f7dba5a337169e854e235da59f595255d6ccAga Madurska final boolean mReverseScroll; 44c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 45c587f7dba5a337169e854e235da59f595255d6ccAga Madurska public GridLayoutManagerSnappingTest(Config config, boolean reverseScroll) { 46c587f7dba5a337169e854e235da59f595255d6ccAga Madurska mConfig = config; 47c587f7dba5a337169e854e235da59f595255d6ccAga Madurska mReverseScroll = reverseScroll; 48c587f7dba5a337169e854e235da59f595255d6ccAga Madurska } 49c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 50e9f9cd8d0e9008340985d17a2541ab24b3adb391Aurimas Liutikas @Parameterized.Parameters(name = "config:{0},reverseScroll:{1}") 51c587f7dba5a337169e854e235da59f595255d6ccAga Madurska public static List<Object[]> getParams() { 52c587f7dba5a337169e854e235da59f595255d6ccAga Madurska List<Object[]> result = new ArrayList<>(); 53c587f7dba5a337169e854e235da59f595255d6ccAga Madurska List<Config> configs = createBaseVariations(); 54c587f7dba5a337169e854e235da59f595255d6ccAga Madurska for (Config config : configs) { 55c587f7dba5a337169e854e235da59f595255d6ccAga Madurska for (boolean reverseScroll : new boolean[] {true, false}) { 56c587f7dba5a337169e854e235da59f595255d6ccAga Madurska result.add(new Object[]{config, reverseScroll}); 57c587f7dba5a337169e854e235da59f595255d6ccAga Madurska } 58c587f7dba5a337169e854e235da59f595255d6ccAga Madurska } 59c587f7dba5a337169e854e235da59f595255d6ccAga Madurska return result; 60c587f7dba5a337169e854e235da59f595255d6ccAga Madurska } 61c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 62c587f7dba5a337169e854e235da59f595255d6ccAga Madurska @Test 63c587f7dba5a337169e854e235da59f595255d6ccAga Madurska public void snapOnScrollSameView() throws Throwable { 64c587f7dba5a337169e854e235da59f595255d6ccAga Madurska final Config config = (Config) mConfig.clone(); 65c587f7dba5a337169e854e235da59f595255d6ccAga Madurska RecyclerView recyclerView = setupBasic(config); 66c587f7dba5a337169e854e235da59f595255d6ccAga Madurska waitForFirstLayout(recyclerView); 67c587f7dba5a337169e854e235da59f595255d6ccAga Madurska setupSnapHelper(); 68c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 69c587f7dba5a337169e854e235da59f595255d6ccAga Madurska // Record the current center view. 70c587f7dba5a337169e854e235da59f595255d6ccAga Madurska View view = findCenterView(mGlm); 71c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertCenterAligned(view); 72c587f7dba5a337169e854e235da59f595255d6ccAga Madurska int scrollDistance = (getViewDimension(view) / 2) - 1; 73c587f7dba5a337169e854e235da59f595255d6ccAga Madurska int scrollDist = mReverseScroll ? -scrollDistance : scrollDistance; 74c587f7dba5a337169e854e235da59f595255d6ccAga Madurska mGlm.expectIdleState(2); 75c587f7dba5a337169e854e235da59f595255d6ccAga Madurska smoothScrollBy(scrollDist); 76c587f7dba5a337169e854e235da59f595255d6ccAga Madurska mGlm.waitForSnap(10); 77c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 78c587f7dba5a337169e854e235da59f595255d6ccAga Madurska // Views have not changed 79c587f7dba5a337169e854e235da59f595255d6ccAga Madurska View viewAfterFling = findCenterView(mGlm); 80c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertSame("The view should have scrolled", view, viewAfterFling); 81c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertCenterAligned(viewAfterFling); 82c587f7dba5a337169e854e235da59f595255d6ccAga Madurska } 83c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 84c587f7dba5a337169e854e235da59f595255d6ccAga Madurska @Test 85c587f7dba5a337169e854e235da59f595255d6ccAga Madurska public void snapOnScrollNextItem() throws Throwable { 86c587f7dba5a337169e854e235da59f595255d6ccAga Madurska final Config config = (Config) mConfig.clone(); 87c587f7dba5a337169e854e235da59f595255d6ccAga Madurska RecyclerView recyclerView = setupBasic(config); 88c587f7dba5a337169e854e235da59f595255d6ccAga Madurska waitForFirstLayout(recyclerView); 89c587f7dba5a337169e854e235da59f595255d6ccAga Madurska setupSnapHelper(); 90c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 91c587f7dba5a337169e854e235da59f595255d6ccAga Madurska // Record the current center view. 92c587f7dba5a337169e854e235da59f595255d6ccAga Madurska View view = findCenterView(mGlm); 93c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertCenterAligned(view); 94c587f7dba5a337169e854e235da59f595255d6ccAga Madurska int scrollDistance = getViewDimension(view) + 1; 95c587f7dba5a337169e854e235da59f595255d6ccAga Madurska int scrollDist = mReverseScroll ? -scrollDistance : scrollDistance; 96c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 97c587f7dba5a337169e854e235da59f595255d6ccAga Madurska smoothScrollBy(scrollDist); 98c587f7dba5a337169e854e235da59f595255d6ccAga Madurska waitForIdleScroll(mRecyclerView); 99c587f7dba5a337169e854e235da59f595255d6ccAga Madurska waitForIdleScroll(mRecyclerView); 100c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 101c587f7dba5a337169e854e235da59f595255d6ccAga Madurska View viewAfterScroll = findCenterView(mGlm); 102c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 103c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertNotSame("The view should have scrolled", view, viewAfterScroll); 104c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertCenterAligned(viewAfterScroll); 105c587f7dba5a337169e854e235da59f595255d6ccAga Madurska } 106c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 107c587f7dba5a337169e854e235da59f595255d6ccAga Madurska @Test 108c587f7dba5a337169e854e235da59f595255d6ccAga Madurska public void snapOnFlingSameView() throws Throwable { 109c587f7dba5a337169e854e235da59f595255d6ccAga Madurska final Config config = (Config) mConfig.clone(); 110c587f7dba5a337169e854e235da59f595255d6ccAga Madurska RecyclerView recyclerView = setupBasic(config); 111c587f7dba5a337169e854e235da59f595255d6ccAga Madurska waitForFirstLayout(recyclerView); 112c587f7dba5a337169e854e235da59f595255d6ccAga Madurska setupSnapHelper(); 113c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 114c587f7dba5a337169e854e235da59f595255d6ccAga Madurska // Record the current center view. 115c587f7dba5a337169e854e235da59f595255d6ccAga Madurska View view = findCenterView(mGlm); 116c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertCenterAligned(view); 117c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 118c587f7dba5a337169e854e235da59f595255d6ccAga Madurska // Velocity small enough to not scroll to the next view. 119c587f7dba5a337169e854e235da59f595255d6ccAga Madurska int velocity = (int) (1.000001 * mRecyclerView.getMinFlingVelocity()); 120c587f7dba5a337169e854e235da59f595255d6ccAga Madurska int velocityDir = mReverseScroll ? -velocity : velocity; 121c587f7dba5a337169e854e235da59f595255d6ccAga Madurska mGlm.expectIdleState(2); 122c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertTrue(fling(velocityDir, velocityDir)); 123c587f7dba5a337169e854e235da59f595255d6ccAga Madurska // Wait for two settling scrolls: the initial one and the corrective one. 124c587f7dba5a337169e854e235da59f595255d6ccAga Madurska waitForIdleScroll(mRecyclerView); 125c587f7dba5a337169e854e235da59f595255d6ccAga Madurska mGlm.waitForSnap(100); 126c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 127c587f7dba5a337169e854e235da59f595255d6ccAga Madurska View viewAfterFling = findCenterView(mGlm); 128c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 129c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertSame("The view should NOT have scrolled", view, viewAfterFling); 130c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertCenterAligned(viewAfterFling); 131c587f7dba5a337169e854e235da59f595255d6ccAga Madurska } 132c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 133c587f7dba5a337169e854e235da59f595255d6ccAga Madurska @Test 134c587f7dba5a337169e854e235da59f595255d6ccAga Madurska public void snapOnFlingNextView() throws Throwable { 135c587f7dba5a337169e854e235da59f595255d6ccAga Madurska final Config config = (Config) mConfig.clone(); 136c587f7dba5a337169e854e235da59f595255d6ccAga Madurska RecyclerView recyclerView = setupBasic(config); 137c587f7dba5a337169e854e235da59f595255d6ccAga Madurska waitForFirstLayout(recyclerView); 138c587f7dba5a337169e854e235da59f595255d6ccAga Madurska setupSnapHelper(); 139c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 140c587f7dba5a337169e854e235da59f595255d6ccAga Madurska // Record the current center view. 141c587f7dba5a337169e854e235da59f595255d6ccAga Madurska View view = findCenterView(mGlm); 142c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertCenterAligned(view); 143c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 144c587f7dba5a337169e854e235da59f595255d6ccAga Madurska // Velocity high enough to scroll beyond the current view. 14524e2d006cef58a0e36a738e0a62a58d0f47e74b6Aga Madurska int velocity = (int) (0.25 * mRecyclerView.getMaxFlingVelocity()); 146c587f7dba5a337169e854e235da59f595255d6ccAga Madurska int velocityDir = mReverseScroll ? -velocity : velocity; 147c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 148c587f7dba5a337169e854e235da59f595255d6ccAga Madurska mGlm.expectIdleState(1); 149c587f7dba5a337169e854e235da59f595255d6ccAga Madurska assertTrue(fling(velocityDir, velocityDir)); 150c587f7dba5a337169e854e235da59f595255d6ccAga Madurska mGlm.waitForSnap(100); 151c587f7dba5a337169e854e235da59f595255d6ccAga Madurska getInstrumentation().waitForIdleSync(); 152c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 153c587f7dba5a337169e854e235da59f595255d6ccAga Madurska View viewAfterFling = findCenterView(mGlm); 154c587f7dba5a337169e854e235da59f595255d6ccAga Madurska 15524e2d006cef58a0e36a738e0a62a58d0f47e74b6Aga Madurska assertNotSame("The view should have scrolled!", 15624e2d006cef58a0e36a738e0a62a58d0f47e74b6Aga Madurska ((TextView) view).getText(),((TextView) viewAfterFling).getText()); 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) + 20624e2d006cef58a0e36a738e0a62a58d0f47e74b6Aga Madurska mGlm.getDecoratedMeasuredWidth(view) / 2, 1); 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) + 21124e2d006cef58a0e36a738e0a62a58d0f47e74b6Aga Madurska mGlm.getDecoratedMeasuredHeight(view) / 2, 1); 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); 22642e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mActivityRule.runOnUiThread(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