173304eff156157f62075215e795e774803a6f96aYigit Boyar/* 273304eff156157f62075215e795e774803a6f96aYigit Boyar * Copyright (C) 2014 The Android Open Source Project 373304eff156157f62075215e795e774803a6f96aYigit Boyar * 473304eff156157f62075215e795e774803a6f96aYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License"); 573304eff156157f62075215e795e774803a6f96aYigit Boyar * you may not use this file except in compliance with the License. 673304eff156157f62075215e795e774803a6f96aYigit Boyar * You may obtain a copy of the License at 773304eff156157f62075215e795e774803a6f96aYigit Boyar * 873304eff156157f62075215e795e774803a6f96aYigit Boyar * http://www.apache.org/licenses/LICENSE-2.0 973304eff156157f62075215e795e774803a6f96aYigit Boyar * 1073304eff156157f62075215e795e774803a6f96aYigit Boyar * Unless required by applicable law or agreed to in writing, software 1173304eff156157f62075215e795e774803a6f96aYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS, 1273304eff156157f62075215e795e774803a6f96aYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1373304eff156157f62075215e795e774803a6f96aYigit Boyar * See the License for the specific language governing permissions and 1473304eff156157f62075215e795e774803a6f96aYigit Boyar * limitations under the License. 1573304eff156157f62075215e795e774803a6f96aYigit Boyar */ 1673304eff156157f62075215e795e774803a6f96aYigit Boyar 1773304eff156157f62075215e795e774803a6f96aYigit Boyarpackage android.support.v7.widget; 1873304eff156157f62075215e795e774803a6f96aYigit Boyar 19e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport static android.support.v7.widget.LinearLayoutManager.HORIZONTAL; 20e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport static android.support.v7.widget.LinearLayoutManager.VERTICAL; 21e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas 22e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport static org.junit.Assert.assertEquals; 23e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport static org.junit.Assert.assertFalse; 24e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport static org.junit.Assert.assertNotNull; 25e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport static org.junit.Assert.assertSame; 26e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport static org.junit.Assert.assertThat; 27e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport static org.junit.Assert.assertTrue; 280a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar 29f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyarimport android.graphics.Color; 30f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyarimport android.graphics.drawable.ColorDrawable; 31f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyarimport android.graphics.drawable.StateListDrawable; 329152a7b54bab69ce0b216c1c7f4b4dcb36190a11Yigit Boyarimport android.os.Build; 339152a7b54bab69ce0b216c1c7f4b4dcb36190a11Yigit Boyarimport android.support.test.filters.SdkSuppress; 340a017072206f93474ccd2706e7983c2ff778b904Yigit Boyarimport android.support.test.runner.AndroidJUnit4; 35a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.AccessibilityDelegateCompat; 36a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyarimport android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; 37bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyarimport android.test.UiThreadTest; 38f1b288ec2104488f4a92e911b0ab80c8f0f3e9d1Yigit Boyarimport android.test.suitebuilder.annotation.MediumTest; 39888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyarimport android.util.SparseIntArray; 40f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyarimport android.util.StateSet; 41061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport android.view.View; 42061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport android.view.ViewGroup; 43061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 44e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport org.hamcrest.CoreMatchers; 45e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport org.junit.Test; 46e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikasimport org.junit.runner.RunWith; 47e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas 48061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport java.util.ArrayList; 49afa0494a97687b705feb3659385578f33f697ea9Yigit Boyarimport java.util.HashMap; 50061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport java.util.List; 51afa0494a97687b705feb3659385578f33f697ea9Yigit Boyarimport java.util.Map; 52888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyarimport java.util.concurrent.atomic.AtomicBoolean; 53061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 54f1b288ec2104488f4a92e911b0ab80c8f0f3e9d1Yigit Boyar@MediumTest 550a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar@RunWith(AndroidJUnit4.class) 564143554adb9b31b700b6876a251a64419e6111e2Yigit Boyarpublic class GridLayoutManagerTest extends BaseGridLayoutManagerTest { 57061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 580a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 590a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void focusSearchFailureUp() throws Throwable { 60f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar focusSearchFailure(false); 61f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar } 62f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar 630a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 640a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void focusSearchFailureDown() throws Throwable { 65f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar focusSearchFailure(true); 66f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar } 67f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar 68f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar @Test 69f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar public void scrollToBadOffset() throws Throwable { 70f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar scrollToBadOffset(false); 71f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } 72f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar 73f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar @Test 74f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar public void scrollToBadOffsetReverse() throws Throwable { 75f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar scrollToBadOffset(true); 76f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } 77f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar 78f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar private void scrollToBadOffset(boolean reverseLayout) throws Throwable { 79f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar final int w = 500; 80f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar final int h = 1000; 81f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar RecyclerView recyclerView = setupBasic(new Config(2, 100).reverseLayout(reverseLayout), 82f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar new GridTestAdapter(100) { 83f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar @Override 84f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar public void onBindViewHolder(TestViewHolder holder, 85f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar int position) { 86f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar super.onBindViewHolder(holder, position); 87f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); 88f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar if (lp == null) { 89f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar lp = new ViewGroup.LayoutParams(w / 2, h / 2); 90f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar holder.itemView.setLayoutParams(lp); 91f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } else { 92f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar lp.width = w / 2; 93f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar lp.height = h / 2; 94f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar holder.itemView.setLayoutParams(lp); 95f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } 96f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } 97f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar }); 98f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar TestedFrameLayout.FullControlLayoutParams lp 99f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar = new TestedFrameLayout.FullControlLayoutParams(w, h); 100f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar recyclerView.setLayoutParams(lp); 101f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar waitForFirstLayout(recyclerView); 102f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar mGlm.expectLayout(1); 103f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar scrollToPosition(11); 104f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar mGlm.waitForLayout(2); 105f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar // assert spans and position etc 106f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar for (int i = 0; i < mGlm.getChildCount(); i++) { 107f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar View child = mGlm.getChildAt(i); 108f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar GridLayoutManager.LayoutParams params = (GridLayoutManager.LayoutParams) child 109f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar .getLayoutParams(); 110f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar assertThat("span index for child at " + i + " with position " + params 111f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar .getViewAdapterPosition(), 112f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar params.getSpanIndex(), CoreMatchers.is(params.getViewAdapterPosition() % 2)); 113f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } 114f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar // assert spans and positions etc. 115f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar int lastVisible = mGlm.findLastVisibleItemPosition(); 116f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar // this should be the scrolled child 117f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar assertThat(lastVisible, CoreMatchers.is(11)); 118f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } 119f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar 1204143554adb9b31b700b6876a251a64419e6111e2Yigit Boyar private void focusSearchFailure(boolean scrollDown) throws Throwable { 121f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar final RecyclerView recyclerView = setupBasic(new Config(3, 31).reverseLayout(!scrollDown) 122f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar , new GridTestAdapter(31, 1) { 123f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar RecyclerView mAttachedRv; 124f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar 125f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar @Override 126f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar public TestViewHolder onCreateViewHolder(ViewGroup parent, 127f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar int viewType) { 128f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar TestViewHolder testViewHolder = super.onCreateViewHolder(parent, viewType); 129f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar testViewHolder.itemView.setFocusable(true); 130f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar testViewHolder.itemView.setFocusableInTouchMode(true); 131f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar // Good to have colors for debugging 132f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar StateListDrawable stl = new StateListDrawable(); 133f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar stl.addState(new int[]{android.R.attr.state_focused}, 134f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar new ColorDrawable(Color.RED)); 135f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar stl.addState(StateSet.WILD_CARD, new ColorDrawable(Color.BLUE)); 1369152a7b54bab69ce0b216c1c7f4b4dcb36190a11Yigit Boyar //noinspection deprecation using this for kitkat tests 1379152a7b54bab69ce0b216c1c7f4b4dcb36190a11Yigit Boyar testViewHolder.itemView.setBackgroundDrawable(stl); 138f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar return testViewHolder; 139f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } 140f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar 141f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar @Override 142f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar public void onAttachedToRecyclerView(RecyclerView recyclerView) { 143f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar mAttachedRv = recyclerView; 144f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } 145f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar 146f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar @Override 147f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar public void onBindViewHolder(TestViewHolder holder, 148f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar int position) { 149f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar super.onBindViewHolder(holder, position); 150f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar holder.itemView.setMinimumHeight(mAttachedRv.getHeight() / 3); 151f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar } 152f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar }); 153f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar waitForFirstLayout(recyclerView); 154f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar 155f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar View viewToFocus = recyclerView.findViewHolderForAdapterPosition(1).itemView; 156959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar assertTrue(requestFocus(viewToFocus, true)); 157f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar assertSame(viewToFocus, recyclerView.getFocusedChild()); 158f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar int pos = 1; 159f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar View focusedView = viewToFocus; 160f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar while (pos < 31) { 161f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar focusSearch(focusedView, scrollDown ? View.FOCUS_DOWN : View.FOCUS_UP); 162959f4c0fac89425a8a9842e82fc180ec736fffacYigit Boyar waitForIdleScroll(recyclerView); 163f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar focusedView = recyclerView.getFocusedChild(); 164f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar assertEquals(Math.min(pos + 3, mAdapter.getItemCount() - 1), 165f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar recyclerView.getChildViewHolder(focusedView).getAdapterPosition()); 166f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar pos += 3; 167f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar } 168f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar } 169f89e1b82c74b7b85df3a349340a643f62fc5bfa1Yigit Boyar 170bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar @UiThreadTest 1710a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1720a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void scrollWithoutLayout() throws Throwable { 173bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar final RecyclerView recyclerView = setupBasic(new Config(3, 100)); 174bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar mGlm.expectLayout(1); 175bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar setRecyclerView(recyclerView); 176bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar mGlm.setSpanCount(5); 177bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar recyclerView.scrollBy(0, 10); 178bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar } 179bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar 1800a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1810a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void scrollWithoutLayoutAfterInvalidate() throws Throwable { 182bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar final RecyclerView recyclerView = setupBasic(new Config(3, 100)); 183bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar waitForFirstLayout(recyclerView); 184bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar runTestOnUiThread(new Runnable() { 185bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar @Override 186bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar public void run() { 187bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar mGlm.setSpanCount(5); 188bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar recyclerView.scrollBy(0, 10); 189bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar } 190bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar }); 191bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar } 192bb2163aca1052da169c15625c9afca7b85491ebfYigit Boyar 1930a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1940a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void predictiveSpanLookup1() throws Throwable { 195cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar predictiveSpanLookupTest(0, false); 196cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar } 197cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar 1980a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 1990a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void predictiveSpanLookup2() throws Throwable { 200cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar predictiveSpanLookupTest(0, true); 201cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar } 202cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar 2030a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 2040a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void predictiveSpanLookup3() throws Throwable { 205cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar predictiveSpanLookupTest(1, false); 206cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar } 207cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar 2080a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 2090a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void predictiveSpanLookup4() throws Throwable { 210cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar predictiveSpanLookupTest(1, true); 211cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar } 212cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar 213cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar public void predictiveSpanLookupTest(int remaining, boolean removeFromStart) throws Throwable { 214cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar RecyclerView recyclerView = setupBasic(new Config(3, 10)); 215cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar mGlm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { 216cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar @Override 217cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar public int getSpanSize(int position) { 218cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar if (position < 0 || position >= mAdapter.getItemCount()) { 219cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar postExceptionToInstrumentation(new AssertionError("position is not within " + 220cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar "adapter range. pos:" + position + ", adapter size:" + 221cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar mAdapter.getItemCount())); 222cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar } 223cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar return 1; 224cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar } 225cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar 226cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar @Override 227cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar public int getSpanIndex(int position, int spanCount) { 228cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar if (position < 0 || position >= mAdapter.getItemCount()) { 229cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar postExceptionToInstrumentation(new AssertionError("position is not within " + 230cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar "adapter range. pos:" + position + ", adapter size:" + 231cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar mAdapter.getItemCount())); 232cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar } 233cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar return super.getSpanIndex(position, spanCount); 234cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar } 235cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar }); 236cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar waitForFirstLayout(recyclerView); 237cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar checkForMainThreadException(); 238cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar assertTrue("test sanity", mGlm.supportsPredictiveItemAnimations()); 239cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar mGlm.expectLayout(2); 240cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar int deleteCnt = 10 - remaining; 241cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar int deleteStart = removeFromStart ? 0 : remaining; 242cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar mAdapter.deleteAndNotify(deleteStart, deleteCnt); 243cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar mGlm.waitForLayout(2); 244cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar checkForMainThreadException(); 245cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar } 246cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar 2470a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 2480a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void movingAGroupOffScreenForAddedItems() throws Throwable { 249888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar final RecyclerView rv = setupBasic(new Config(3, 100)); 250888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar final int[] maxId = new int[1]; 251888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar maxId[0] = -1; 252888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar final SparseIntArray spanLookups = new SparseIntArray(); 253888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar final AtomicBoolean enableSpanLookupLogging = new AtomicBoolean(false); 254888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar mGlm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { 255888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar @Override 256888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar public int getSpanSize(int position) { 257888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar if (maxId[0] > 0 && mAdapter.getItemAt(position).mId > maxId[0]) { 258888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar return 1; 259888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar } else if (enableSpanLookupLogging.get() && !rv.mState.isPreLayout()) { 260888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar spanLookups.put(position, spanLookups.get(position, 0) + 1); 261888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar } 262888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar return 3; 263888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar } 264888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar }); 265f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar ((SimpleItemAnimator) rv.getItemAnimator()).setSupportsChangeAnimations(true); 266888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar waitForFirstLayout(rv); 267888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar View lastView = rv.getChildAt(rv.getChildCount() - 1); 268888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar final int lastPos = rv.getChildAdapterPosition(lastView); 269888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar maxId[0] = mAdapter.getItemAt(mAdapter.getItemCount() - 1).mId; 270888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar // now add a lot of items below this and those new views should have span size 3 271888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar enableSpanLookupLogging.set(true); 272888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar mGlm.expectLayout(2); 273888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar mAdapter.addAndNotify(lastPos - 2, 30); 274888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar mGlm.waitForLayout(2); 275888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar checkForMainThreadException(); 276888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar 277888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar assertEquals("last items span count should be queried twice", 2, 278888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar spanLookups.get(lastPos + 30)); 279888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar 280888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar } 281888093b0a071a99d65c01116cf703d46b21f9918Yigit Boyar 2820a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 2830a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void layoutParams() throws Throwable { 284061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar layoutParamsTest(GridLayoutManager.HORIZONTAL); 285061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar removeRecyclerView(); 286061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar layoutParamsTest(GridLayoutManager.VERTICAL); 287061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 288061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 2890a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 2909152a7b54bab69ce0b216c1c7f4b4dcb36190a11Yigit Boyar @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT) 2910a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void horizontalAccessibilitySpanIndices() throws Throwable { 292a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar accessibilitySpanIndicesTest(HORIZONTAL); 293a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 294a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 2950a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 2969152a7b54bab69ce0b216c1c7f4b4dcb36190a11Yigit Boyar @SdkSuppress(minSdkVersion = Build.VERSION_CODES.KITKAT) 2970a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void verticalAccessibilitySpanIndices() throws Throwable { 298a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar accessibilitySpanIndicesTest(VERTICAL); 299a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 300a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 301a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public void accessibilitySpanIndicesTest(int orientation) throws Throwable { 302a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final RecyclerView recyclerView = setupBasic(new Config(3, orientation, false)); 303a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar waitForFirstLayout(recyclerView); 304a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AccessibilityDelegateCompat delegateCompat = mRecyclerView 305a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar .getCompatAccessibilityDelegate().getItemDelegate(); 306a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(); 307a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final View chosen = recyclerView.getChildAt(recyclerView.getChildCount() - 2); 308115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar final int position = recyclerView.getChildLayoutPosition(chosen); 309a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar runTestOnUiThread(new Runnable() { 310a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 311a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public void run() { 312a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar delegateCompat.onInitializeAccessibilityNodeInfo(chosen, info); 313a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 314a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar }); 315a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar GridLayoutManager.SpanSizeLookup ssl = mGlm.mSpanSizeLookup; 316a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar AccessibilityNodeInfoCompat.CollectionItemInfoCompat itemInfo = info 317a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar .getCollectionItemInfo(); 318a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertNotNull(itemInfo); 319a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals("result should have span group position", 320a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar ssl.getSpanGroupIndex(position, mGlm.getSpanCount()), 321a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar orientation == HORIZONTAL ? itemInfo.getColumnIndex() : itemInfo.getRowIndex()); 322a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals("result should have span index", 323a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar ssl.getSpanIndex(position, mGlm.getSpanCount()), 324f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar orientation == HORIZONTAL ? itemInfo.getRowIndex() : itemInfo.getColumnIndex()); 325a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals("result should have span size", 326a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar ssl.getSpanSize(position), 327f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar orientation == HORIZONTAL ? itemInfo.getRowSpan() : itemInfo.getColumnSpan()); 328a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 329a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 330afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar public GridLayoutManager.LayoutParams ensureGridLp(View view) { 331afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar ViewGroup.LayoutParams lp = view.getLayoutParams(); 332afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar GridLayoutManager.LayoutParams glp; 333afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar if (lp instanceof GridLayoutManager.LayoutParams) { 334afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar glp = (GridLayoutManager.LayoutParams) lp; 335afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } else if (lp == null) { 336afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar glp = (GridLayoutManager.LayoutParams) mGlm 337afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar .generateDefaultLayoutParams(); 338afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar view.setLayoutParams(glp); 339afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } else { 340afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar glp = (GridLayoutManager.LayoutParams) mGlm.generateLayoutParams(lp); 341afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar view.setLayoutParams(glp); 342afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 343afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar return glp; 344afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 345afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar 346061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void layoutParamsTest(final int orientation) throws Throwable { 347061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final RecyclerView rv = setupBasic(new Config(3, 100).orientation(orientation), 348061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar new GridTestAdapter(100) { 349061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 350061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void onBindViewHolder(TestViewHolder holder, 351061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int position) { 352061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar super.onBindViewHolder(holder, position); 353afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar GridLayoutManager.LayoutParams glp = ensureGridLp(holder.itemView); 354061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int val = 0; 355061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar switch (position % 5) { 356061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 0: 357061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar val = 10; 358061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 359061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 1: 360061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar val = 30; 361061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 362061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 2: 363061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar val = GridLayoutManager.LayoutParams.WRAP_CONTENT; 364061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 365061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 3: 366e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas val = GridLayoutManager.LayoutParams.MATCH_PARENT; 367061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 368061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 4: 369061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar val = 200; 370061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 371061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 372061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (orientation == GridLayoutManager.VERTICAL) { 373061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar glp.height = val; 374061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } else { 375061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar glp.width = val; 376061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 377061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar holder.itemView.setLayoutParams(glp); 378061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 379061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar }); 380061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar waitForFirstLayout(rv); 381061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final OrientationHelper helper = mGlm.mOrientationHelper; 382061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final int firstRowSize = Math.max(30, getSize(mGlm.findViewByPosition(2))); 383115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar assertEquals(firstRowSize, 384115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar helper.getDecoratedMeasurement(mGlm.findViewByPosition(0))); 385115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar assertEquals(firstRowSize, 386115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar helper.getDecoratedMeasurement(mGlm.findViewByPosition(1))); 387115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar assertEquals(firstRowSize, 388115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar helper.getDecoratedMeasurement(mGlm.findViewByPosition(2))); 389061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(firstRowSize, getSize(mGlm.findViewByPosition(0))); 390061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(firstRowSize, getSize(mGlm.findViewByPosition(1))); 391061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(firstRowSize, getSize(mGlm.findViewByPosition(2))); 392061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 393061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final int secondRowSize = Math.max(200, getSize(mGlm.findViewByPosition(3))); 394115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar assertEquals(secondRowSize, 395115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar helper.getDecoratedMeasurement(mGlm.findViewByPosition(3))); 396115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar assertEquals(secondRowSize, 397115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar helper.getDecoratedMeasurement(mGlm.findViewByPosition(4))); 398115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar assertEquals(secondRowSize, 399115ba0c7b2a14aa4cd0273952195e1d8f6468f87Yigit Boyar helper.getDecoratedMeasurement(mGlm.findViewByPosition(5))); 400061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(secondRowSize, getSize(mGlm.findViewByPosition(3))); 401061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(secondRowSize, getSize(mGlm.findViewByPosition(4))); 402061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(secondRowSize, getSize(mGlm.findViewByPosition(5))); 403061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 404061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 4050a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 4060a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void anchorUpdate() throws InterruptedException { 40773304eff156157f62075215e795e774803a6f96aYigit Boyar GridLayoutManager glm = new GridLayoutManager(getActivity(), 11); 40873304eff156157f62075215e795e774803a6f96aYigit Boyar final GridLayoutManager.SpanSizeLookup spanSizeLookup 40973304eff156157f62075215e795e774803a6f96aYigit Boyar = new GridLayoutManager.SpanSizeLookup() { 41073304eff156157f62075215e795e774803a6f96aYigit Boyar @Override 41173304eff156157f62075215e795e774803a6f96aYigit Boyar public int getSpanSize(int position) { 41273304eff156157f62075215e795e774803a6f96aYigit Boyar if (position > 200) { 41373304eff156157f62075215e795e774803a6f96aYigit Boyar return 100; 41473304eff156157f62075215e795e774803a6f96aYigit Boyar } 41573304eff156157f62075215e795e774803a6f96aYigit Boyar if (position > 20) { 41673304eff156157f62075215e795e774803a6f96aYigit Boyar return 2; 41773304eff156157f62075215e795e774803a6f96aYigit Boyar } 41873304eff156157f62075215e795e774803a6f96aYigit Boyar return 1; 41973304eff156157f62075215e795e774803a6f96aYigit Boyar } 42073304eff156157f62075215e795e774803a6f96aYigit Boyar }; 42173304eff156157f62075215e795e774803a6f96aYigit Boyar glm.setSpanSizeLookup(spanSizeLookup); 42273304eff156157f62075215e795e774803a6f96aYigit Boyar glm.mAnchorInfo.mPosition = 11; 42342c4af4ff383daf001263ae18a9b00b9fbf87487Yigit Boyar RecyclerView.State state = new RecyclerView.State(); 424cf87e0b2827dba309646d6a73945b2e1d1fac248Yigit Boyar mRecyclerView = new RecyclerView(getActivity()); 425061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar state.mItemCount = 1000; 426f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.onAnchorReady(mRecyclerView.mRecycler, state, glm.mAnchorInfo, 427f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar LinearLayoutManager.LayoutState.ITEM_DIRECTION_TAIL); 42873304eff156157f62075215e795e774803a6f96aYigit Boyar assertEquals("gm should keep anchor in first span", 11, glm.mAnchorInfo.mPosition); 42973304eff156157f62075215e795e774803a6f96aYigit Boyar 430f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.onAnchorReady(mRecyclerView.mRecycler, state, glm.mAnchorInfo, 431f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar LinearLayoutManager.LayoutState.ITEM_DIRECTION_HEAD); 432f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar assertEquals("gm should keep anchor in last span in the row", 20, 433f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.mAnchorInfo.mPosition); 434f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar 435f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.mAnchorInfo.mPosition = 5; 436f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.onAnchorReady(mRecyclerView.mRecycler, state, glm.mAnchorInfo, 437f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar LinearLayoutManager.LayoutState.ITEM_DIRECTION_HEAD); 438f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar assertEquals("gm should keep anchor in last span in the row", 10, 439f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.mAnchorInfo.mPosition); 440f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar 44173304eff156157f62075215e795e774803a6f96aYigit Boyar glm.mAnchorInfo.mPosition = 13; 442f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.onAnchorReady(mRecyclerView.mRecycler, state, glm.mAnchorInfo, 443f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar LinearLayoutManager.LayoutState.ITEM_DIRECTION_TAIL); 44473304eff156157f62075215e795e774803a6f96aYigit Boyar assertEquals("gm should move anchor to first span", 11, glm.mAnchorInfo.mPosition); 44573304eff156157f62075215e795e774803a6f96aYigit Boyar 446f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.onAnchorReady(mRecyclerView.mRecycler, state, glm.mAnchorInfo, 447f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar LinearLayoutManager.LayoutState.ITEM_DIRECTION_HEAD); 448f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar assertEquals("gm should keep anchor in last span in the row", 20, 449f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.mAnchorInfo.mPosition); 450f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar 45173304eff156157f62075215e795e774803a6f96aYigit Boyar glm.mAnchorInfo.mPosition = 23; 452f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.onAnchorReady(mRecyclerView.mRecycler, state, glm.mAnchorInfo, 453f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar LinearLayoutManager.LayoutState.ITEM_DIRECTION_TAIL); 45473304eff156157f62075215e795e774803a6f96aYigit Boyar assertEquals("gm should move anchor to first span", 21, glm.mAnchorInfo.mPosition); 45573304eff156157f62075215e795e774803a6f96aYigit Boyar 456f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.onAnchorReady(mRecyclerView.mRecycler, state, glm.mAnchorInfo, 457f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar LinearLayoutManager.LayoutState.ITEM_DIRECTION_HEAD); 458f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar assertEquals("gm should keep anchor in last span in the row", 25, 459f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.mAnchorInfo.mPosition); 460f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar 46173304eff156157f62075215e795e774803a6f96aYigit Boyar glm.mAnchorInfo.mPosition = 35; 462f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.onAnchorReady(mRecyclerView.mRecycler, state, glm.mAnchorInfo, 463f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar LinearLayoutManager.LayoutState.ITEM_DIRECTION_TAIL); 46473304eff156157f62075215e795e774803a6f96aYigit Boyar assertEquals("gm should move anchor to first span", 31, glm.mAnchorInfo.mPosition); 465f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.onAnchorReady(mRecyclerView.mRecycler, state, glm.mAnchorInfo, 466f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar LinearLayoutManager.LayoutState.ITEM_DIRECTION_HEAD); 467f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar assertEquals("gm should keep anchor in last span in the row", 35, 468f7f1c1ef2a0e0696fbfa8065ac88cd1f8dd39623Yigit Boyar glm.mAnchorInfo.mPosition); 46973304eff156157f62075215e795e774803a6f96aYigit Boyar } 47073304eff156157f62075215e795e774803a6f96aYigit Boyar 4710a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 4720a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void spanLookup() { 473061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar spanLookupTest(false); 474061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 475061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 4760a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 4770a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void spanLookupWithCache() { 478061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar spanLookupTest(true); 479061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 480061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 4810a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 4820a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void spanLookupCache() { 483061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final GridLayoutManager.SpanSizeLookup ssl 484061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar = new GridLayoutManager.SpanSizeLookup() { 485061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 486061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public int getSpanSize(int position) { 487061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (position > 6) { 488061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return 2; 489061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 490061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return 1; 491061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 492061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar }; 493061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.setSpanIndexCacheEnabled(true); 494061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child non existent", -1, ssl.findReferenceIndexFromCache(2)); 495061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.getCachedSpanIndex(4, 5); 496061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child non existent", -1, ssl.findReferenceIndexFromCache(3)); 497061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar // this should not happen and if happens, it is better to return -1 498061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child itself", -1, ssl.findReferenceIndexFromCache(4)); 499061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 4, ssl.findReferenceIndexFromCache(5)); 500061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 4, ssl.findReferenceIndexFromCache(100)); 501061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.getCachedSpanIndex(6, 5); 502061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 6, ssl.findReferenceIndexFromCache(7)); 503061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 4, ssl.findReferenceIndexFromCache(6)); 504061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child itself", -1, ssl.findReferenceIndexFromCache(4)); 505061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.getCachedSpanIndex(12, 5); 506061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 12, ssl.findReferenceIndexFromCache(13)); 507061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 6, ssl.findReferenceIndexFromCache(12)); 508061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 6, ssl.findReferenceIndexFromCache(7)); 509061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int i = 0; i < 6; i++) { 510061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.getCachedSpanIndex(i, 5); 511061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 512061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 513061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int i = 1; i < 7; i++) { 514061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child right before " + i, i - 1, 515061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.findReferenceIndexFromCache(i)); 516061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 517061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before 0 ", -1, ssl.findReferenceIndexFromCache(0)); 518061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 519061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 520061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void spanLookupTest(boolean enableCache) { 52173304eff156157f62075215e795e774803a6f96aYigit Boyar final GridLayoutManager.SpanSizeLookup ssl 52273304eff156157f62075215e795e774803a6f96aYigit Boyar = new GridLayoutManager.SpanSizeLookup() { 52373304eff156157f62075215e795e774803a6f96aYigit Boyar @Override 52473304eff156157f62075215e795e774803a6f96aYigit Boyar public int getSpanSize(int position) { 52573304eff156157f62075215e795e774803a6f96aYigit Boyar if (position > 200) { 52673304eff156157f62075215e795e774803a6f96aYigit Boyar return 100; 52773304eff156157f62075215e795e774803a6f96aYigit Boyar } 52873304eff156157f62075215e795e774803a6f96aYigit Boyar if (position > 6) { 52973304eff156157f62075215e795e774803a6f96aYigit Boyar return 2; 53073304eff156157f62075215e795e774803a6f96aYigit Boyar } 53173304eff156157f62075215e795e774803a6f96aYigit Boyar return 1; 53273304eff156157f62075215e795e774803a6f96aYigit Boyar } 53373304eff156157f62075215e795e774803a6f96aYigit Boyar }; 534061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.setSpanIndexCacheEnabled(enableCache); 535061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(0, ssl.getCachedSpanIndex(0, 5)); 536061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(4, ssl.getCachedSpanIndex(4, 5)); 537061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(0, ssl.getCachedSpanIndex(5, 5)); 538061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(1, ssl.getCachedSpanIndex(6, 5)); 539061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(2, ssl.getCachedSpanIndex(7, 5)); 540061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(2, ssl.getCachedSpanIndex(9, 5)); 541061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(0, ssl.getCachedSpanIndex(8, 5)); 542061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 543061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 5440a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 5450a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void removeAnchorItem() throws Throwable { 5461f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar removeAnchorItemTest( 5471f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar new Config(3, 0).orientation(VERTICAL).reverseLayout(false), 100, 0); 5481f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 5491f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar 5500a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 5510a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void removeAnchorItemReverse() throws Throwable { 5521f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar removeAnchorItemTest( 5531f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar new Config(3, 0).orientation(VERTICAL).reverseLayout(true), 100, 5541f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar 0); 5551f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 5561f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar 5570a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 5580a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void removeAnchorItemHorizontal() throws Throwable { 5591f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar removeAnchorItemTest( 5601f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar new Config(3, 0).orientation(HORIZONTAL).reverseLayout( 5611f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar false), 100, 0); 5621f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 5631f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar 5640a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 5650a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void removeAnchorItemReverseHorizontal() throws Throwable { 5661f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar removeAnchorItemTest( 5671f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar new Config(3, 0).orientation(HORIZONTAL).reverseLayout(true), 5681f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar 100, 0); 5691f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 5701f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar 5711f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar /** 5721f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar * This tests a regression where predictive animations were not working as expected when the 5731f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar * first item is removed and there aren't any more items to add from that direction. 5741f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar * First item refers to the default anchor item. 5751f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar */ 5761f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar public void removeAnchorItemTest(final Config config, int adapterSize, 5771f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar final int removePos) throws Throwable { 5781f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar GridTestAdapter adapter = new GridTestAdapter(adapterSize) { 5791f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar @Override 5801f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar public void onBindViewHolder(TestViewHolder holder, 5811f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar int position) { 5821f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar super.onBindViewHolder(holder, position); 5831f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); 5841f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar if (!(lp instanceof ViewGroup.MarginLayoutParams)) { 5851f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar lp = new ViewGroup.MarginLayoutParams(0, 0); 5861f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar holder.itemView.setLayoutParams(lp); 5871f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 5881f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) lp; 5891f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar final int maxSize; 5901f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar if (config.mOrientation == HORIZONTAL) { 5911f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar maxSize = mRecyclerView.getWidth(); 592e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas mlp.height = ViewGroup.MarginLayoutParams.MATCH_PARENT; 5931f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } else { 5941f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar maxSize = mRecyclerView.getHeight(); 595e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas mlp.width = ViewGroup.MarginLayoutParams.MATCH_PARENT; 5961f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 5971f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar 5981f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar final int desiredSize; 5991f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar if (position == removePos) { 6001f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar // make it large 6011f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar desiredSize = maxSize / 4; 6021f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } else { 6031f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar // make it small 6041f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar desiredSize = maxSize / 8; 6051f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6061f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar if (config.mOrientation == HORIZONTAL) { 6071f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar mlp.width = desiredSize; 6081f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } else { 6091f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar mlp.height = desiredSize; 6101f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6111f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6121f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar }; 6131f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar RecyclerView recyclerView = setupBasic(config, adapter); 6141f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar waitForFirstLayout(recyclerView); 6151f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar final int childCount = mGlm.getChildCount(); 6161f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar RecyclerView.ViewHolder toBeRemoved = null; 6171f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar List<RecyclerView.ViewHolder> toBeMoved = new ArrayList<RecyclerView.ViewHolder>(); 6181f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar for (int i = 0; i < childCount; i++) { 6191f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar View child = mGlm.getChildAt(i); 6201f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(child); 6211f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar if (holder.getAdapterPosition() == removePos) { 6221f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar toBeRemoved = holder; 6231f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } else { 6241f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar toBeMoved.add(holder); 6251f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6261f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6271f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar assertNotNull("test sanity", toBeRemoved); 6281f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar assertEquals("test sanity", childCount - 1, toBeMoved.size()); 6291f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar LoggingItemAnimator loggingItemAnimator = new LoggingItemAnimator(); 6301f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar mRecyclerView.setItemAnimator(loggingItemAnimator); 6311f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar loggingItemAnimator.reset(); 6321f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar loggingItemAnimator.expectRunPendingAnimationsCall(1); 6331f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar mGlm.expectLayout(2); 6341f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar adapter.deleteAndNotify(removePos, 1); 6351f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar mGlm.waitForLayout(1); 6361f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar loggingItemAnimator.waitForPendingAnimationsCall(2); 6371f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar assertTrue("removed child should receive remove animation", 6381f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar loggingItemAnimator.mRemoveVHs.contains(toBeRemoved)); 6391f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar for (RecyclerView.ViewHolder vh : toBeMoved) { 6401f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar assertTrue("view holder should be in moved list", 6411f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar loggingItemAnimator.mMoveVHs.contains(vh)); 6421f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6431f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar List<RecyclerView.ViewHolder> newHolders = new ArrayList<RecyclerView.ViewHolder>(); 6441f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar for (int i = 0; i < mGlm.getChildCount(); i++) { 6451f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar View child = mGlm.getChildAt(i); 6461f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(child); 6471f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar if (toBeRemoved != holder && !toBeMoved.contains(holder)) { 6481f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar newHolders.add(holder); 6491f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6501f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6511f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar assertTrue("some new children should show up for the new space", newHolders.size() > 0); 6521f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar assertEquals("no items should receive animate add since they are not new", 0, 6531f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar loggingItemAnimator.mAddVHs.size()); 6541f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar for (RecyclerView.ViewHolder holder : newHolders) { 6551f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar assertTrue("new holder should receive a move animation", 6561f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar loggingItemAnimator.mMoveVHs.contains(holder)); 6571f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6581f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar // for removed view, 3 for new row 6591f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar assertTrue("control against adding too many children due to bad layout state preparation." 6601f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar + " initial:" + childCount + ", current:" + mRecyclerView.getChildCount(), 6611f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar mRecyclerView.getChildCount() <= childCount + 1 + 3); 6621f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar } 6631f5c7b76bfc3da85513e6d2c6aa1058339f0c625Yigit Boyar 6640a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 6650a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void spanGroupIndex() { 666a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar final GridLayoutManager.SpanSizeLookup ssl 667a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar = new GridLayoutManager.SpanSizeLookup() { 668a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar @Override 669a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar public int getSpanSize(int position) { 670a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar if (position > 200) { 671a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return 100; 672a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 673a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar if (position > 6) { 674a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return 2; 675a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 676a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar return 1; 677a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 678a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar }; 679a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(0, ssl.getSpanGroupIndex(0, 5)); 680a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(0, ssl.getSpanGroupIndex(4, 5)); 681a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(1, ssl.getSpanGroupIndex(5, 5)); 682a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(1, ssl.getSpanGroupIndex(6, 5)); 683a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(1, ssl.getSpanGroupIndex(7, 5)); 684a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(2, ssl.getSpanGroupIndex(9, 5)); 685a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar assertEquals(2, ssl.getSpanGroupIndex(8, 5)); 686a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar } 687a910619e83d0052e1d81aa5fe532821a2f99d76cYigit Boyar 6880a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 6890a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void notifyDataSetChange() throws Throwable { 690061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final RecyclerView recyclerView = setupBasic(new Config(3, 100)); 691061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final GridLayoutManager.SpanSizeLookup ssl = mGlm.getSpanSizeLookup(); 692061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.setSpanIndexCacheEnabled(true); 693061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar waitForFirstLayout(recyclerView); 694061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertTrue("some positions should be cached", ssl.mSpanIndexCache.size() > 0); 695061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final Callback callback = new Callback() { 696061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 697061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void onBeforeLayout(RecyclerView.Recycler recycler, RecyclerView.State state) { 698061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (!state.isPreLayout()) { 699061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("cache should be empty", 0, ssl.mSpanIndexCache.size()); 700061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 701061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 702061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 703061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 704061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void onAfterLayout(RecyclerView.Recycler recycler, RecyclerView.State state) { 705061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (!state.isPreLayout()) { 706061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertTrue("some items should be cached", ssl.mSpanIndexCache.size() > 0); 707061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 708061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 709061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar }; 710061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.mCallbacks.add(callback); 711061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.expectLayout(2); 712061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mAdapter.deleteAndNotify(2, 3); 713061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.waitForLayout(2); 714061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar checkForMainThreadException(); 715061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 716061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 7170a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 7180a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void unevenHeights() throws Throwable { 719afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar final Map<Integer, RecyclerView.ViewHolder> viewHolderMap = 720afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar new HashMap<Integer, RecyclerView.ViewHolder>(); 721afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar RecyclerView recyclerView = setupBasic(new Config(3, 3), new GridTestAdapter(3) { 722afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar @Override 723afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar public void onBindViewHolder(TestViewHolder holder, 724afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar int position) { 725afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar super.onBindViewHolder(holder, position); 726afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar final GridLayoutManager.LayoutParams glp = ensureGridLp(holder.itemView); 727afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar glp.height = 50 + position * 50; 728afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar viewHolderMap.put(position, holder); 729afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 730afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar }); 731afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar waitForFirstLayout(recyclerView); 732afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar for (RecyclerView.ViewHolder vh : viewHolderMap.values()) { 733afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar assertEquals("all items should get max height", 150, 734afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar vh.itemView.getHeight()); 735afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 736afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar 737afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar for (RecyclerView.ViewHolder vh : viewHolderMap.values()) { 738afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar assertEquals("all items should have measured the max height", 150, 739afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar vh.itemView.getMeasuredHeight()); 740afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 741afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 742afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar 7430a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 7440a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void unevenWidths() throws Throwable { 745afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar final Map<Integer, RecyclerView.ViewHolder> viewHolderMap = 746afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar new HashMap<Integer, RecyclerView.ViewHolder>(); 747afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar RecyclerView recyclerView = setupBasic(new Config(3, HORIZONTAL, false), 748afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar new GridTestAdapter(3) { 749afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar @Override 750afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar public void onBindViewHolder(TestViewHolder holder, 751afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar int position) { 752afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar super.onBindViewHolder(holder, position); 753afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar final GridLayoutManager.LayoutParams glp = ensureGridLp(holder.itemView); 754afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar glp.width = 50 + position * 50; 755afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar viewHolderMap.put(position, holder); 756afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 757afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar }); 758afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar waitForFirstLayout(recyclerView); 759afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar for (RecyclerView.ViewHolder vh : viewHolderMap.values()) { 760afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar assertEquals("all items should get max width", 150, 761afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar vh.itemView.getWidth()); 762afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 763afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar 764afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar for (RecyclerView.ViewHolder vh : viewHolderMap.values()) { 765afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar assertEquals("all items should have measured the max width", 150, 766afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar vh.itemView.getMeasuredWidth()); 767afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 768afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar } 769afa0494a97687b705feb3659385578f33f697ea9Yigit Boyar 7700a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 7710a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void spanSizeChange() throws Throwable { 772204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar final RecyclerView rv = setupBasic(new Config(3, 100)); 773204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar waitForFirstLayout(rv); 774204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar assertTrue(mGlm.supportsPredictiveItemAnimations()); 775204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar mGlm.expectLayout(1); 776204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar runTestOnUiThread(new Runnable() { 777204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar @Override 778204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar public void run() { 779204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar mGlm.setSpanCount(5); 780204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar assertFalse(mGlm.supportsPredictiveItemAnimations()); 781204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar } 782204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar }); 783204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar mGlm.waitForLayout(2); 784204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar mGlm.expectLayout(2); 785204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar mAdapter.deleteAndNotify(3, 2); 786204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar mGlm.waitForLayout(2); 787204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar assertTrue(mGlm.supportsPredictiveItemAnimations()); 788204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar } 789204f79ca6e0d6253c10a80da11056b03cb9d3fb0Yigit Boyar 7900a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar @Test 7910a017072206f93474ccd2706e7983c2ff778b904Yigit Boyar public void cacheSpanIndices() throws Throwable { 792061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final RecyclerView rv = setupBasic(new Config(3, 100)); 793061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.mSpanSizeLookup.setSpanIndexCacheEnabled(true); 794061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar waitForFirstLayout(rv); 795061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar GridLayoutManager.SpanSizeLookup ssl = mGlm.mSpanSizeLookup; 796061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertTrue("cache should be filled", mGlm.mSpanSizeLookup.mSpanIndexCache.size() > 0); 797061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("item index 5 should be in span 2", 2, 798061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar getLp(mGlm.findViewByPosition(5)).getSpanIndex()); 799061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.expectLayout(2); 800061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mAdapter.mFullSpanItems.add(4); 801061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mAdapter.changeAndNotify(4, 1); 802061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.waitForLayout(2); 803061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("item index 5 should be in span 2", 0, 804061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar getLp(mGlm.findViewByPosition(5)).getSpanIndex()); 805061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 80673304eff156157f62075215e795e774803a6f96aYigit Boyar} 807