1e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar/* 2ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikas * Copyright 2018 The Android Open Source Project 3e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * 4e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 5e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * you may not use this file except in compliance with the License. 6e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * You may obtain a copy of the License at 7e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * 8e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 9e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * 10e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * Unless required by applicable law or agreed to in writing, software 11e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 12e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * See the License for the specific language governing permissions and 14e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar * limitations under the License. 15e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar */ 16e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 17ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikaspackage androidx.recyclerview.widget; 18e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 19ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.recyclerview.widget.ItemTouchHelper.END; 20ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.recyclerview.widget.ItemTouchHelper.LEFT; 21ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.recyclerview.widget.ItemTouchHelper.RIGHT; 22ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.recyclerview.widget.ItemTouchHelper.START; 23ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport static androidx.recyclerview.widget.ItemTouchHelper.SimpleCallback; 240a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 25754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertEquals; 26754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertNotNull; 27754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport static org.junit.Assert.assertTrue; 2845d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikas 2945d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikasimport android.os.Build; 3035232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikasimport android.support.test.filters.LargeTest; 3145d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikasimport android.support.test.filters.SdkSuppress; 32fb06780abd4844c38173c183afff0fca3d954193Aurimas Liutikasimport android.support.test.filters.Suppress; 330a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport android.support.test.runner.AndroidJUnit4; 34e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyarimport android.view.Gravity; 35350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapardimport android.view.View; 3645d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikas 37c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.annotation.NonNull; 38c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.core.util.Pair; 39c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikasimport androidx.testutils.PollingCheck; 40c95a6f1f125ad3a7e1f9f79bccf4b2603bc40ebaAurimas Liutikas 4145d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikasimport org.junit.Test; 4245d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikasimport org.junit.runner.RunWith; 43e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 44e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyarimport java.util.ArrayList; 45e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyarimport java.util.List; 46e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 4735232c6eaeb9b99f390cb8ef0ac83bf45fa0b3faAurimas Liutikas@LargeTest 480a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar@RunWith(AndroidJUnit4.class) 49e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyarpublic class ItemTouchHelperTest extends BaseRecyclerViewInstrumentationTest { 50e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 51350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard private static class RecyclerViewState { 52350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard public TestAdapter mAdapter; 53350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard public TestLayoutManager mLayoutManager; 54350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard public WrappedRecyclerView mWrappedRecyclerView; 55350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard } 56e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 57e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private LoggingCalback mCalback; 58e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 59e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private LoggingItemTouchHelper mItemTouchHelper; 60e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 61e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private Boolean mSetupRTL; 62e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 63e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public ItemTouchHelperTest() { 64e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar super(false); 65e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 66e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 67350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard private RecyclerViewState setupRecyclerView() throws Throwable { 68350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard RecyclerViewState rvs = new RecyclerViewState(); 69350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mWrappedRecyclerView = inflateWrappedRV(); 70350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mAdapter = new TestAdapter(10); 71350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mLayoutManager = new TestLayoutManager() { 72e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar @Override 73e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 74e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar detachAndScrapAttachedViews(recycler); 75e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar layoutRange(recycler, 0, Math.min(5, state.getItemCount())); 76e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar layoutLatch.countDown(); 77e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 78e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 79e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar @Override 80e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public boolean canScrollHorizontally() { 81e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar return false; 82e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 83e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 84e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar @Override 85e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public boolean supportsPredictiveItemAnimations() { 86e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar return false; 87e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 88e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar }; 89350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mWrappedRecyclerView.setFakeRTL(mSetupRTL); 90350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mWrappedRecyclerView.setAdapter(rvs.mAdapter); 91350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mWrappedRecyclerView.setLayoutManager(rvs.mLayoutManager); 92350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard return rvs; 93350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard } 94350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard 95350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard private RecyclerViewState setupItemTouchHelper(final RecyclerViewState rvs, int dragDirs, 96350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard int swipeDirs) throws Throwable { 97e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar mCalback = new LoggingCalback(dragDirs, swipeDirs); 98e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar mItemTouchHelper = new LoggingItemTouchHelper(mCalback); 9942e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas mActivityRule.runOnUiThread(new Runnable() { 100629687bba8da1a73c48d8fe87393a13581ce46caYigit Boyar @Override 101629687bba8da1a73c48d8fe87393a13581ce46caYigit Boyar public void run() { 102350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard mItemTouchHelper.attachToRecyclerView(rvs.mWrappedRecyclerView); 103629687bba8da1a73c48d8fe87393a13581ce46caYigit Boyar } 104629687bba8da1a73c48d8fe87393a13581ce46caYigit Boyar }); 105629687bba8da1a73c48d8fe87393a13581ce46caYigit Boyar 106350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard return rvs; 107e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 108e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 1090a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1100a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void swipeLeft() throws Throwable { 111e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar basicSwipeTest(LEFT, LEFT | RIGHT, -getActivity().getWindow().getDecorView().getWidth()); 112e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 113e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 1140a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1150a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void swipeRight() throws Throwable { 116e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar basicSwipeTest(RIGHT, LEFT | RIGHT, getActivity().getWindow().getDecorView().getWidth()); 117e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 118e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 1190a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1200a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void swipeStart() throws Throwable { 121e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar basicSwipeTest(START, START | END, -getActivity().getWindow().getDecorView().getWidth()); 122e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 123e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 1240a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1250a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void swipeEnd() throws Throwable { 126e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar basicSwipeTest(END, START | END, getActivity().getWindow().getDecorView().getWidth()); 127e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 128e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 129fb06780abd4844c38173c183afff0fca3d954193Aurimas Liutikas // Test is disabled as it is flaky. 130fb06780abd4844c38173c183afff0fca3d954193Aurimas Liutikas @Suppress 13145d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikas @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN_MR1) 1320a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1330a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void swipeStartInRTL() throws Throwable { 134e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar mSetupRTL = true; 135e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar basicSwipeTest(START, START | END, getActivity().getWindow().getDecorView().getWidth()); 136e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 137e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 13845d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikas @SdkSuppress(minSdkVersion = Build.VERSION_CODES.JELLY_BEAN_MR1) 1390a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1400a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void swipeEndInRTL() throws Throwable { 141e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar mSetupRTL = true; 142e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar basicSwipeTest(END, START | END, -getActivity().getWindow().getDecorView().getWidth()); 143e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 144e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 145350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard @Test 146350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard public void attachToNullRecycleViewDuringLongPress() throws Throwable { 147350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard final RecyclerViewState rvs = setupItemTouchHelper(setupRecyclerView(), END, 0); 148350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mLayoutManager.expectLayouts(1); 149350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard setRecyclerView(rvs.mWrappedRecyclerView); 150350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mLayoutManager.waitForLayout(1); 151350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard 152350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard final RecyclerView.ViewHolder target = mRecyclerView 153350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard .findViewHolderForAdapterPosition(1); 154350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard target.itemView.setOnLongClickListener(new View.OnLongClickListener() { 155350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard @Override 156350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard public boolean onLongClick(View v) { 157350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard mItemTouchHelper.attachToRecyclerView(null); 158350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard return false; 159350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard } 160350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard }); 161350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard TouchUtils.longClickView(getInstrumentation(), target.itemView); 162350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard } 163350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard 164350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard @Test 165350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard public void attachToAnotherRecycleViewDuringLongPress() throws Throwable { 166350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard final RecyclerViewState rvs2 = setupRecyclerView(); 167350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs2.mLayoutManager.expectLayouts(1); 168350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard mActivityRule.runOnUiThread(new Runnable() { 169350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard @Override 170350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard public void run() { 171350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard getActivity().getContainer().addView(rvs2.mWrappedRecyclerView); 172350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard } 173350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard }); 174350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs2.mLayoutManager.waitForLayout(1); 175350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard 176350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard final RecyclerViewState rvs = setupItemTouchHelper(setupRecyclerView(), END, 0); 177350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mLayoutManager.expectLayouts(1); 178350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard setRecyclerView(rvs.mWrappedRecyclerView); 179350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mLayoutManager.waitForLayout(1); 180350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard 181350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard final RecyclerView.ViewHolder target = mRecyclerView 182350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard .findViewHolderForAdapterPosition(1); 183350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard target.itemView.setOnLongClickListener(new View.OnLongClickListener() { 184350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard @Override 185350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard public boolean onLongClick(View v) { 186350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard mItemTouchHelper.attachToRecyclerView(rvs2.mWrappedRecyclerView); 187350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard return false; 188350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard } 189350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard }); 190350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard TouchUtils.longClickView(getInstrumentation(), target.itemView); 191350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard assertEquals(0, mCalback.mHasDragFlag.size()); 192350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard } 193350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard 194e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public void basicSwipeTest(int dir, int swipeDirs, int targetX) throws Throwable { 195350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard final RecyclerViewState rvs = setupItemTouchHelper(setupRecyclerView(), 0, swipeDirs); 196350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mLayoutManager.expectLayouts(1); 197350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard setRecyclerView(rvs.mWrappedRecyclerView); 198350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mLayoutManager.waitForLayout(1); 199e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 200e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar final RecyclerView.ViewHolder target = mRecyclerView 201e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar .findViewHolderForAdapterPosition(1); 2020a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar TouchUtils.dragViewToX(getInstrumentation(), target.itemView, Gravity.CENTER, targetX); 203277b9d6d56ba5a21240710b27c6e431498392a08Aurimas Liutikas 204277b9d6d56ba5a21240710b27c6e431498392a08Aurimas Liutikas PollingCheck.waitFor(1000, new PollingCheck.PollingCheckCondition() { 205277b9d6d56ba5a21240710b27c6e431498392a08Aurimas Liutikas @Override 206277b9d6d56ba5a21240710b27c6e431498392a08Aurimas Liutikas public boolean canProceed() { 207277b9d6d56ba5a21240710b27c6e431498392a08Aurimas Liutikas return mCalback.getSwipe(target) != null; 208277b9d6d56ba5a21240710b27c6e431498392a08Aurimas Liutikas } 209277b9d6d56ba5a21240710b27c6e431498392a08Aurimas Liutikas }); 210e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar final SwipeRecord swipe = mCalback.getSwipe(target); 211e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar assertNotNull(swipe); 212e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar assertEquals(dir, swipe.dir); 213e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar assertEquals(1, mItemTouchHelper.mRecoverAnimations.size()); 214e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar assertEquals(1, mItemTouchHelper.mPendingCleanup.size()); 215e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar // get rid of the view 216350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mLayoutManager.expectLayouts(1); 217350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mAdapter.deleteAndNotify(1, 1); 218350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard rvs.mLayoutManager.waitForLayout(1); 219e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar waitForAnimations(); 220e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar assertEquals(0, mItemTouchHelper.mRecoverAnimations.size()); 221e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar assertEquals(0, mItemTouchHelper.mPendingCleanup.size()); 222e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar assertTrue(mCalback.isCleared(target)); 223e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 224e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 225e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private void waitForAnimations() throws InterruptedException { 226e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar while (mRecyclerView.getItemAnimator().isRunning()) { 227e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar Thread.sleep(100); 228e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 229e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 230e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 231e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private static class LoggingCalback extends SimpleCallback { 232e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 233e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private List<MoveRecord> mMoveRecordList = new ArrayList<MoveRecord>(); 234e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 235e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private List<SwipeRecord> mSwipeRecords = new ArrayList<SwipeRecord>(); 236e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 237e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private List<RecyclerView.ViewHolder> mCleared = new ArrayList<RecyclerView.ViewHolder>(); 238e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 239350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard public List<Pair<RecyclerView, RecyclerView.ViewHolder>> mHasDragFlag = new ArrayList<>(); 240350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard 24145d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikas LoggingCalback(int dragDirs, int swipeDirs) { 242e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar super(dragDirs, swipeDirs); 243e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 244e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 245e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar @Override 2468a11e6829c522aa1efcc903afa4c01d337082eabChris Craik public boolean onMove(@NonNull RecyclerView recyclerView, 2478a11e6829c522aa1efcc903afa4c01d337082eabChris Craik @NonNull RecyclerView.ViewHolder viewHolder, 2488a11e6829c522aa1efcc903afa4c01d337082eabChris Craik @NonNull RecyclerView.ViewHolder target) { 249e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar mMoveRecordList.add(new MoveRecord(viewHolder, target)); 250e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar return true; 251e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 252e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 253e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar @Override 2548a11e6829c522aa1efcc903afa4c01d337082eabChris Craik public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) { 255e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar mSwipeRecords.add(new SwipeRecord(viewHolder, direction)); 256e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 257e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 258e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public MoveRecord getMove(RecyclerView.ViewHolder vh) { 259e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar for (MoveRecord move : mMoveRecordList) { 260e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar if (move.from == vh) { 261e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar return move; 262e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 263e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 264e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar return null; 265e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 266e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 267e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar @Override 2688a11e6829c522aa1efcc903afa4c01d337082eabChris Craik public void clearView(@NonNull RecyclerView recyclerView, 2698a11e6829c522aa1efcc903afa4c01d337082eabChris Craik @NonNull RecyclerView.ViewHolder viewHolder) { 270e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar super.clearView(recyclerView, viewHolder); 271e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar mCleared.add(viewHolder); 272e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 273e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 274350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard @Override 275350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard boolean hasDragFlag(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 276350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard mHasDragFlag.add(new Pair<>(recyclerView, viewHolder)); 277350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard return super.hasDragFlag(recyclerView, viewHolder); 278350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard } 279350a38a3cc040891c3f94b1fd9c1642aa29a7db3shepshapard 280e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public SwipeRecord getSwipe(RecyclerView.ViewHolder vh) { 281e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar for (SwipeRecord swipe : mSwipeRecords) { 282e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar if (swipe.viewHolder == vh) { 283e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar return swipe; 284e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 285e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 286e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar return null; 287e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 288e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 289e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public boolean isCleared(RecyclerView.ViewHolder vh) { 290e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar return mCleared.contains(vh); 291e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 292e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 293e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 294e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private static class LoggingItemTouchHelper extends ItemTouchHelper { 295e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 296e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public LoggingItemTouchHelper(Callback callback) { 297e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar super(callback); 298e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 299e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 300e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 301e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private static class SwipeRecord { 302e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 303e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar RecyclerView.ViewHolder viewHolder; 304e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 305e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar int dir; 306e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 307e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar public SwipeRecord(RecyclerView.ViewHolder viewHolder, int dir) { 308e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar this.viewHolder = viewHolder; 309e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar this.dir = dir; 310e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 311e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 312e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 313e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar private static class MoveRecord { 314e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 315e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar final int fromPos, toPos; 316e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 317e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar RecyclerView.ViewHolder from, to; 318e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar 31945d07c8efb62ee378db48884989e5b05b5494981Aurimas Liutikas MoveRecord(RecyclerView.ViewHolder from, RecyclerView.ViewHolder to) { 320e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar this.from = from; 321e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar this.to = to; 322e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar fromPos = from.getAdapterPosition(); 323e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar toPos = to.getAdapterPosition(); 324e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 325e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar } 326e71a1df9b3c0e1bd3c21a1b3dd20a41790d4a950Yigit Boyar} 327