GridLayoutManagerTest.java revision 061c3284cf284424ae084799dd7ba5c8d6d59faa
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 19061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport android.content.Context; 20061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport android.util.Log; 21061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport android.view.View; 22061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport android.view.ViewGroup; 23061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 24061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport java.util.ArrayList; 25061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport java.util.Arrays; 26061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport java.util.BitSet; 27061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport java.util.HashSet; 28061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport java.util.List; 29061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport java.util.Set; 30061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport java.util.concurrent.CountDownLatch; 31061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 32061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport static android.support.v7.widget.LinearLayoutManager.HORIZONTAL; 33061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport static android.support.v7.widget.LinearLayoutManager.VERTICAL; 34061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyarimport static java.util.concurrent.TimeUnit.SECONDS; 35061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 3673304eff156157f62075215e795e774803a6f96aYigit Boyarpublic class GridLayoutManagerTest extends BaseRecyclerViewInstrumentationTest { 37061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 38061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar static final String TAG = "GridLayoutManagerTest"; 39061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 40061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar static final boolean DEBUG = false; 41061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 42061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar WrappedGridLayoutManager mGlm; 43061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 44061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar GridTestAdapter mAdapter; 45061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 46061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final List<Config> mBaseVariations = new ArrayList<Config>(); 47061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 48061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 49061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar protected void setUp() throws Exception { 50061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar super.setUp(); 51061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int orientation : new int[]{VERTICAL, HORIZONTAL}) { 52061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (boolean reverseLayout : new boolean[]{false, true}) { 53061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int spanCount : new int[]{1, 3, 4}) { 54061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mBaseVariations.add(new Config(spanCount, orientation, reverseLayout)); 55061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 56061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 57061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 58061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 59061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 60061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public RecyclerView setupBasic(Config config) throws Throwable { 61061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return setupBasic(config, new GridTestAdapter(config.mItemCount)); 62061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 63061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 64061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public RecyclerView setupBasic(Config config, GridTestAdapter testAdapter) throws Throwable { 65061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar RecyclerView recyclerView = new RecyclerView(getActivity()); 66061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mAdapter = testAdapter; 67061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm = new WrappedGridLayoutManager(getActivity(), config.mSpanCount, config.mOrientation, 68061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar config.mReverseLayout); 69061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mAdapter.assignSpanSizeLookup(mGlm); 70061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar recyclerView.setAdapter(mAdapter); 71061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar recyclerView.setLayoutManager(mGlm); 72061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return recyclerView; 73061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 74061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 75061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void waitForFirstLayout(RecyclerView recyclerView) throws Throwable { 76061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.expectLayout(1); 77061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar setRecyclerView(recyclerView); 78061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.waitForLayout(2); 79061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 80061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 81061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void testLayoutParams() throws Throwable { 82061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar layoutParamsTest(GridLayoutManager.HORIZONTAL); 83061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar removeRecyclerView(); 84061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar layoutParamsTest(GridLayoutManager.VERTICAL); 85061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 86061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 87061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void layoutParamsTest(final int orientation) throws Throwable { 88061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final RecyclerView rv = setupBasic(new Config(3, 100).orientation(orientation), 89061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar new GridTestAdapter(100) { 90061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 91061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void onBindViewHolder(TestViewHolder holder, 92061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int position) { 93061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar super.onBindViewHolder(holder, position); 94061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams(); 95061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar GridLayoutManager.LayoutParams glp = null; 96061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (lp == null) { 97061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar glp = (GridLayoutManager.LayoutParams) mGlm 98061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar .generateDefaultLayoutParams(); 99061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } else { 100061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar glp = (GridLayoutManager.LayoutParams) mGlm.generateLayoutParams(lp); 101061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 102061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int val = 0; 103061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar switch (position % 5) { 104061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 0: 105061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar val = 10; 106061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 107061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 1: 108061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar val = 30; 109061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 110061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 2: 111061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar val = GridLayoutManager.LayoutParams.WRAP_CONTENT; 112061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 113061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 3: 114061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar val = GridLayoutManager.LayoutParams.FILL_PARENT; 115061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 116061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar case 4: 117061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar val = 200; 118061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar break; 119061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 120061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (orientation == GridLayoutManager.VERTICAL) { 121061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar glp.height = val; 122061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } else { 123061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar glp.width = val; 124061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 125061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar holder.itemView.setLayoutParams(glp); 126061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 127061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar }); 128061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar waitForFirstLayout(rv); 129061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final OrientationHelper helper = mGlm.mOrientationHelper; 130061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final int firstRowSize = Math.max(30, getSize(mGlm.findViewByPosition(2))); 131061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(10, helper.getDecoratedMeasurement(mGlm.findViewByPosition(0))); 132061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(30, helper.getDecoratedMeasurement(mGlm.findViewByPosition(1))); 133061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(firstRowSize, getSize(mGlm.findViewByPosition(0))); 134061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(firstRowSize, getSize(mGlm.findViewByPosition(1))); 135061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(firstRowSize, getSize(mGlm.findViewByPosition(2))); 136061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 137061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final int secondRowSize = Math.max(200, getSize(mGlm.findViewByPosition(3))); 138061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(200, helper.getDecoratedMeasurement(mGlm.findViewByPosition(4))); 139061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(secondRowSize, getSize(mGlm.findViewByPosition(3))); 140061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(secondRowSize, getSize(mGlm.findViewByPosition(4))); 141061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(secondRowSize, getSize(mGlm.findViewByPosition(5))); 142061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 143061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 144061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar private int getSize(View view) { 145061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (mGlm.getOrientation() == GridLayoutManager.HORIZONTAL) { 146061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return view.getWidth(); 147061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 148061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return view.getHeight(); 149061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 150061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 15173304eff156157f62075215e795e774803a6f96aYigit Boyar public void testAnchorUpdate() throws InterruptedException { 15273304eff156157f62075215e795e774803a6f96aYigit Boyar GridLayoutManager glm = new GridLayoutManager(getActivity(), 11); 15373304eff156157f62075215e795e774803a6f96aYigit Boyar final GridLayoutManager.SpanSizeLookup spanSizeLookup 15473304eff156157f62075215e795e774803a6f96aYigit Boyar = new GridLayoutManager.SpanSizeLookup() { 15573304eff156157f62075215e795e774803a6f96aYigit Boyar @Override 15673304eff156157f62075215e795e774803a6f96aYigit Boyar public int getSpanSize(int position) { 15773304eff156157f62075215e795e774803a6f96aYigit Boyar if (position > 200) { 15873304eff156157f62075215e795e774803a6f96aYigit Boyar return 100; 15973304eff156157f62075215e795e774803a6f96aYigit Boyar } 16073304eff156157f62075215e795e774803a6f96aYigit Boyar if (position > 20) { 16173304eff156157f62075215e795e774803a6f96aYigit Boyar return 2; 16273304eff156157f62075215e795e774803a6f96aYigit Boyar } 16373304eff156157f62075215e795e774803a6f96aYigit Boyar return 1; 16473304eff156157f62075215e795e774803a6f96aYigit Boyar } 16573304eff156157f62075215e795e774803a6f96aYigit Boyar }; 16673304eff156157f62075215e795e774803a6f96aYigit Boyar glm.setSpanSizeLookup(spanSizeLookup); 16773304eff156157f62075215e795e774803a6f96aYigit Boyar glm.mAnchorInfo.mPosition = 11; 16842c4af4ff383daf001263ae18a9b00b9fbf87487Yigit Boyar RecyclerView.State state = new RecyclerView.State(); 169061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar state.mItemCount = 1000; 1709ace89f49ed497e649b127beb12b8a237e5d30e7Yigit Boyar glm.onAnchorReady(state, glm.mAnchorInfo); 17173304eff156157f62075215e795e774803a6f96aYigit Boyar assertEquals("gm should keep anchor in first span", 11, glm.mAnchorInfo.mPosition); 17273304eff156157f62075215e795e774803a6f96aYigit Boyar 17373304eff156157f62075215e795e774803a6f96aYigit Boyar glm.mAnchorInfo.mPosition = 13; 1749ace89f49ed497e649b127beb12b8a237e5d30e7Yigit Boyar glm.onAnchorReady(state, glm.mAnchorInfo); 17573304eff156157f62075215e795e774803a6f96aYigit Boyar assertEquals("gm should move anchor to first span", 11, glm.mAnchorInfo.mPosition); 17673304eff156157f62075215e795e774803a6f96aYigit Boyar 17773304eff156157f62075215e795e774803a6f96aYigit Boyar glm.mAnchorInfo.mPosition = 23; 1789ace89f49ed497e649b127beb12b8a237e5d30e7Yigit Boyar glm.onAnchorReady(state, glm.mAnchorInfo); 17973304eff156157f62075215e795e774803a6f96aYigit Boyar assertEquals("gm should move anchor to first span", 21, glm.mAnchorInfo.mPosition); 18073304eff156157f62075215e795e774803a6f96aYigit Boyar 18173304eff156157f62075215e795e774803a6f96aYigit Boyar glm.mAnchorInfo.mPosition = 35; 1829ace89f49ed497e649b127beb12b8a237e5d30e7Yigit Boyar glm.onAnchorReady(state, glm.mAnchorInfo); 18373304eff156157f62075215e795e774803a6f96aYigit Boyar assertEquals("gm should move anchor to first span", 31, glm.mAnchorInfo.mPosition); 18473304eff156157f62075215e795e774803a6f96aYigit Boyar } 18573304eff156157f62075215e795e774803a6f96aYigit Boyar 18673304eff156157f62075215e795e774803a6f96aYigit Boyar public void testSpanLookup() { 187061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar spanLookupTest(false); 188061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 189061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 190061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void testSpanLookupWithCache() { 191061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar spanLookupTest(true); 192061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 193061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 194061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void testSpanLookupCache() { 195061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final GridLayoutManager.SpanSizeLookup ssl 196061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar = new GridLayoutManager.SpanSizeLookup() { 197061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 198061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public int getSpanSize(int position) { 199061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (position > 6) { 200061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return 2; 201061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 202061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return 1; 203061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 204061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar }; 205061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.setSpanIndexCacheEnabled(true); 206061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child non existent", -1, ssl.findReferenceIndexFromCache(2)); 207061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.getCachedSpanIndex(4, 5); 208061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child non existent", -1, ssl.findReferenceIndexFromCache(3)); 209061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar // this should not happen and if happens, it is better to return -1 210061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child itself", -1, ssl.findReferenceIndexFromCache(4)); 211061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 4, ssl.findReferenceIndexFromCache(5)); 212061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 4, ssl.findReferenceIndexFromCache(100)); 213061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.getCachedSpanIndex(6, 5); 214061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 6, ssl.findReferenceIndexFromCache(7)); 215061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 4, ssl.findReferenceIndexFromCache(6)); 216061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child itself", -1, ssl.findReferenceIndexFromCache(4)); 217061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.getCachedSpanIndex(12, 5); 218061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 12, ssl.findReferenceIndexFromCache(13)); 219061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 6, ssl.findReferenceIndexFromCache(12)); 220061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before", 6, ssl.findReferenceIndexFromCache(7)); 221061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int i = 0; i < 6; i++) { 222061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.getCachedSpanIndex(i, 5); 223061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 224061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 225061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int i = 1; i < 7; i++) { 226061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child right before " + i, i - 1, 227061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.findReferenceIndexFromCache(i)); 228061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 229061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("reference child before 0 ", -1, ssl.findReferenceIndexFromCache(0)); 230061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 231061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 232061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void spanLookupTest(boolean enableCache) { 23373304eff156157f62075215e795e774803a6f96aYigit Boyar final GridLayoutManager.SpanSizeLookup ssl 23473304eff156157f62075215e795e774803a6f96aYigit Boyar = new GridLayoutManager.SpanSizeLookup() { 23573304eff156157f62075215e795e774803a6f96aYigit Boyar @Override 23673304eff156157f62075215e795e774803a6f96aYigit Boyar public int getSpanSize(int position) { 23773304eff156157f62075215e795e774803a6f96aYigit Boyar if (position > 200) { 23873304eff156157f62075215e795e774803a6f96aYigit Boyar return 100; 23973304eff156157f62075215e795e774803a6f96aYigit Boyar } 24073304eff156157f62075215e795e774803a6f96aYigit Boyar if (position > 6) { 24173304eff156157f62075215e795e774803a6f96aYigit Boyar return 2; 24273304eff156157f62075215e795e774803a6f96aYigit Boyar } 24373304eff156157f62075215e795e774803a6f96aYigit Boyar return 1; 24473304eff156157f62075215e795e774803a6f96aYigit Boyar } 24573304eff156157f62075215e795e774803a6f96aYigit Boyar }; 246061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.setSpanIndexCacheEnabled(enableCache); 247061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(0, ssl.getCachedSpanIndex(0, 5)); 248061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(4, ssl.getCachedSpanIndex(4, 5)); 249061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(0, ssl.getCachedSpanIndex(5, 5)); 250061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(1, ssl.getCachedSpanIndex(6, 5)); 251061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(2, ssl.getCachedSpanIndex(7, 5)); 252061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(2, ssl.getCachedSpanIndex(9, 5)); 253061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(0, ssl.getCachedSpanIndex(8, 5)); 254061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 255061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 256061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void testNotifyDataSetChange() throws Throwable { 257061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final RecyclerView recyclerView = setupBasic(new Config(3, 100)); 258061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final GridLayoutManager.SpanSizeLookup ssl = mGlm.getSpanSizeLookup(); 259061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ssl.setSpanIndexCacheEnabled(true); 260061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar waitForFirstLayout(recyclerView); 261061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertTrue("some positions should be cached", ssl.mSpanIndexCache.size() > 0); 262061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final Callback callback = new Callback() { 263061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 264061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void onBeforeLayout(RecyclerView.Recycler recycler, RecyclerView.State state) { 265061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (!state.isPreLayout()) { 266061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("cache should be empty", 0, ssl.mSpanIndexCache.size()); 267061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 268061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 269061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 270061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 271061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void onAfterLayout(RecyclerView.Recycler recycler, RecyclerView.State state) { 272061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (!state.isPreLayout()) { 273061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertTrue("some items should be cached", ssl.mSpanIndexCache.size() > 0); 274061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 275061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 276061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar }; 277061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.mCallbacks.add(callback); 278061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.expectLayout(2); 279061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mAdapter.deleteAndNotify(2, 3); 280061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.waitForLayout(2); 281061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar checkForMainThreadException(); 282061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 283061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 284061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void testScrollBackAndPreservePositions() throws Throwable { 285061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (Config config : mBaseVariations) { 286061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar config.mItemCount = 150; 287061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar scrollBackAndPreservePositionsTest(config); 288061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar removeRecyclerView(); 289061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 290061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 291061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 292061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void testCacheSpanIndices() throws Throwable { 293061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final RecyclerView rv = setupBasic(new Config(3, 100)); 294061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.mSpanSizeLookup.setSpanIndexCacheEnabled(true); 295061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar waitForFirstLayout(rv); 296061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar GridLayoutManager.SpanSizeLookup ssl = mGlm.mSpanSizeLookup; 297061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertTrue("cache should be filled", mGlm.mSpanSizeLookup.mSpanIndexCache.size() > 0); 298061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("item index 5 should be in span 2", 2, 299061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar getLp(mGlm.findViewByPosition(5)).getSpanIndex()); 300061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.expectLayout(2); 301061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mAdapter.mFullSpanItems.add(4); 302061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mAdapter.changeAndNotify(4, 1); 303061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.waitForLayout(2); 304061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("item index 5 should be in span 2", 0, 305061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar getLp(mGlm.findViewByPosition(5)).getSpanIndex()); 306061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 307061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 308061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar GridLayoutManager.LayoutParams getLp(View view) { 309061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return (GridLayoutManager.LayoutParams) view.getLayoutParams(); 310061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 311061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 312061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void scrollBackAndPreservePositionsTest(final Config config) throws Throwable { 313061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final RecyclerView rv = setupBasic(config); 314061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int i = 1; i < mAdapter.getItemCount(); i += config.mSpanCount + 2) { 315061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mAdapter.setFullSpan(i); 316061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 317061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar waitForFirstLayout(rv); 318061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final int[] globalPositions = new int[mAdapter.getItemCount()]; 319061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar Arrays.fill(globalPositions, Integer.MIN_VALUE); 320061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final int scrollStep = (mGlm.mOrientationHelper.getTotalSpace() / 20) 321061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar * (config.mReverseLayout ? -1 : 1); 322061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final String logPrefix = config.toString(); 323061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final int[] globalPos = new int[1]; 324061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar runTestOnUiThread(new Runnable() { 325061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 326061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void run() { 327061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int globalScrollPosition = 0; 328061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int visited = 0; 329061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar while (visited < mAdapter.getItemCount()) { 330061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int i = 0; i < mRecyclerView.getChildCount(); i++) { 331061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar View child = mRecyclerView.getChildAt(i); 332061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar final int pos = mRecyclerView.getChildPosition(child); 333061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (globalPositions[pos] != Integer.MIN_VALUE) { 334061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar continue; 335061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 336061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar visited++; 337061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) 338061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar child.getLayoutParams(); 339061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (config.mReverseLayout) { 340061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar globalPositions[pos] = globalScrollPosition + 341061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.mOrientationHelper.getDecoratedEnd(child); 342061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } else { 343061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar globalPositions[pos] = globalScrollPosition + 344061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.mOrientationHelper.getDecoratedStart(child); 345061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 346061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(logPrefix + " span index should match", 347061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.getSpanSizeLookup().getSpanIndex(pos, mGlm.getSpanCount()), 348061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar lp.getSpanIndex()); 349061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 350061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int scrolled = mGlm.scrollBy(scrollStep, 351061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mRecyclerView.mRecycler, mRecyclerView.mState); 352061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar globalScrollPosition += scrolled; 353061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (scrolled == 0) { 354061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals( 355061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar logPrefix + " If scroll is complete, all views should be visited", 356061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar visited, mAdapter.getItemCount()); 357061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 358061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 359061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (DEBUG) { 360061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar Log.d(TAG, "done recording positions " + Arrays.toString(globalPositions)); 361061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 362061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar globalPos[0] = globalScrollPosition; 363061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 364061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar }); 365061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar checkForMainThreadException(); 366061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar runTestOnUiThread(new Runnable() { 367061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 368061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void run() { 369061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int globalScrollPosition = globalPos[0]; 370061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar // now scroll back and make sure global positions match 371061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar BitSet shouldTest = new BitSet(mAdapter.getItemCount()); 372061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar shouldTest.set(0, mAdapter.getItemCount() - 1, true); 373061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar String assertPrefix = config 374061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar + " global pos must match when scrolling in reverse for position "; 375061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int scrollAmount = Integer.MAX_VALUE; 376061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar while (!shouldTest.isEmpty() && scrollAmount != 0) { 377061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int i = 0; i < mRecyclerView.getChildCount(); i++) { 378061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar View child = mRecyclerView.getChildAt(i); 379061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int pos = mRecyclerView.getChildPosition(child); 380061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (!shouldTest.get(pos)) { 381061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar continue; 382061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 383061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar GridLayoutManager.LayoutParams lp = (GridLayoutManager.LayoutParams) 384061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar child.getLayoutParams(); 385061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar shouldTest.clear(pos); 386061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int globalPos; 387061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar if (config.mReverseLayout) { 388061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar globalPos = globalScrollPosition + 389061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.mOrientationHelper.getDecoratedEnd(child); 390061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } else { 391061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar globalPos = globalScrollPosition + 392061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.mOrientationHelper.getDecoratedStart(child); 393061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 394061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals(assertPrefix + pos, 395061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar globalPositions[pos], globalPos); 396061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertEquals("span index should match", 397061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mGlm.getSpanSizeLookup().getSpanIndex(pos, mGlm.getSpanCount()), 398061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar lp.getSpanIndex()); 399061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 400061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar scrollAmount = mGlm.scrollBy(-scrollStep, 401061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mRecyclerView.mRecycler, mRecyclerView.mState); 402061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar globalScrollPosition += scrollAmount; 403061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 404061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar assertTrue("all views should be seen", shouldTest.isEmpty()); 405061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 406061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar }); 407061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar checkForMainThreadException(); 408061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 409061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 410061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar class WrappedGridLayoutManager extends GridLayoutManager { 411061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 412061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar CountDownLatch mLayoutLatch; 413061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 414061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar List<Callback> mCallbacks = new ArrayList<Callback>(); 415061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 416061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public WrappedGridLayoutManager(Context context, int spanCount) { 417061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar super(context, spanCount); 418061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 419061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 420061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public WrappedGridLayoutManager(Context context, int spanCount, int orientation, 421061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar boolean reverseLayout) { 422061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar super(context, spanCount, orientation, reverseLayout); 423061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 424061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 425061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 426061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) { 427061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar try { 428061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (Callback callback : mCallbacks) { 429061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar callback.onBeforeLayout(recycler, state); 430061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 431061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar super.onLayoutChildren(recycler, state); 432061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (Callback callback : mCallbacks) { 433061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar callback.onAfterLayout(recycler, state); 434061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 435061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } catch (Throwable t) { 436061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar postExceptionToInstrumentation(t); 437061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 438061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mLayoutLatch.countDown(); 439061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 440061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 441061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void expectLayout(int layoutCount) { 442061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mLayoutLatch = new CountDownLatch(layoutCount); 443061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 444061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 445061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void waitForLayout(int seconds) throws InterruptedException { 446061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mLayoutLatch.await(seconds, SECONDS); 447061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 448061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 449061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 450061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar class Config { 451061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 452061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int mSpanCount; 453061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int mOrientation = GridLayoutManager.VERTICAL; 454061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar int mItemCount = 1000; 455061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar boolean mReverseLayout = false; 456061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 457061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar Config(int spanCount, int itemCount) { 458061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mSpanCount = spanCount; 459061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mItemCount = itemCount; 460061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 461061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 462061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public Config(int spanCount, int orientation, boolean reverseLayout) { 463061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mSpanCount = spanCount; 464061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mOrientation = orientation; 465061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mReverseLayout = reverseLayout; 466061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 467061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 468061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar Config orientation(int orientation) { 469061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mOrientation = orientation; 470061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return this; 471061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 472061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 473061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 474061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public String toString() { 475061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return "Config{" + 476061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar "mSpanCount=" + mSpanCount + 477061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ", mOrientation=" + (mOrientation == GridLayoutManager.HORIZONTAL ? "h" : "v") + 478061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ", mItemCount=" + mItemCount + 479061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar ", mReverseLayout=" + mReverseLayout + 480061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar '}'; 481061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 482061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 483061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 484061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar class GridTestAdapter extends TestAdapter { 485061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 486061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar Set<Integer> mFullSpanItems = new HashSet<Integer>(); 487061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 488061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar GridTestAdapter(int count) { 489061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar super(count); 490061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 491061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 492061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar void setFullSpan(int... items) { 493061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar for (int i : items) { 494061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar mFullSpanItems.add(i); 495061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 496061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 497061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 498061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar void assignSpanSizeLookup(final GridLayoutManager glm) { 499061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { 500061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar @Override 501061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public int getSpanSize(int position) { 502061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar return mFullSpanItems.contains(position) ? glm.getSpanCount() : 1; 503061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 504061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar }); 505061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 506061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 507061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 508061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar class Callback { 509061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 510061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void onBeforeLayout(RecyclerView.Recycler recycler, RecyclerView.State state) { 511061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 512061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar 513061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar public void onAfterLayout(RecyclerView.Recycler recycler, RecyclerView.State state) { 514061c3284cf284424ae084799dd7ba5c8d6d59faaYigit Boyar } 51573304eff156157f62075215e795e774803a6f96aYigit Boyar } 51673304eff156157f62075215e795e774803a6f96aYigit Boyar} 517