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