18cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar/*
28cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * Copyright (C) 2016 The Android Open Source Project
38cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar *
48cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * Licensed under the Apache License, Version 2.0 (the "License");
58cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * you may not use this file except in compliance with the License.
68cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * You may obtain a copy of the License at
78cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar *
88cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar *      http://www.apache.org/licenses/LICENSE-2.0
98cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar *
108cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * Unless required by applicable law or agreed to in writing, software
118cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * distributed under the License is distributed on an "AS IS" BASIS,
128cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * See the License for the specific language governing permissions and
148cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * limitations under the License.
158cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar */
168cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar
178cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarpackage android.support.v7.widget;
188cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar
198cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport static android.view.View.MeasureSpec.AT_MOST;
208cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport static android.view.View.MeasureSpec.EXACTLY;
218cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport static android.view.View.MeasureSpec.makeMeasureSpec;
228cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar
238cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport static org.hamcrest.CoreMatchers.is;
248cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport static org.hamcrest.CoreMatchers.notNullValue;
258cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport static org.hamcrest.MatcherAssert.assertThat;
268cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar
278cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport android.graphics.Rect;
28754cb29c50f09a83251dd4bb633ba445b2411adbAurimas Liutikasimport android.support.test.filters.MediumTest;
298cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport android.support.test.runner.AndroidJUnit4;
308cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport android.view.View;
318cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar
328cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport org.junit.Test;
338cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarimport org.junit.runner.RunWith;
348cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar
358cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar/**
368cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * Tests scroll to position with wrap content to make sure that LayoutManagers can keep track of
378cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar * the position if layout is called multiple times.
388cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar */
398cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar@MediumTest
408cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar@RunWith(AndroidJUnit4.class)
418cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyarpublic class ScrollToPositionWithAutoMeasure extends BaseRecyclerViewInstrumentationTest {
428cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    @Test
438cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    public void testLinearLayoutManager() throws Throwable {
448cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        LinearLayoutManager llm = new LinearLayoutManager(getActivity());
458cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        llm.ensureLayoutState();
468cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        test(llm, llm.mOrientationHelper);
478cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    }
488cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar
498cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    @Test
508cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    public void testGridLayoutManager() throws Throwable {
518cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        GridLayoutManager glm = new GridLayoutManager(getActivity(), 3);
528cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        glm.ensureLayoutState();
538cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        test(glm, glm.mOrientationHelper);
548cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    }
558cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar
568cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    @Test
578cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    public void testStaggeredGridLayoutManager() throws Throwable {
588cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        StaggeredGridLayoutManager sglm = new StaggeredGridLayoutManager(3,
598cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                StaggeredGridLayoutManager.VERTICAL);
608cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        test(sglm, sglm.mPrimaryOrientation);
618cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    }
628cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar
638cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    public void test(final RecyclerView.LayoutManager llm,
648cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar            final OrientationHelper orientationHelper) throws Throwable {
658cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        final RecyclerView recyclerView = new RecyclerView(getActivity());
668cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        recyclerView.setLayoutManager(llm);
678cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        recyclerView.setAdapter(new TestAdapter(1000));
688cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        setRecyclerView(recyclerView);
698cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        getInstrumentation().waitForIdleSync();
708cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        assertThat("Test sanity", recyclerView.getChildCount() > 0, is(true));
7142e7d6fafcde7bfe261dd7d8d75ee53ca0cd6790Aurimas Liutikas        mActivityRule.runOnUiThread(new Runnable() {
728cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar            @Override
738cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar            public void run() {
748cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                View lastChild = llm.getChildAt(llm.getChildCount() - 1);
758cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                int lastChildPos = recyclerView.getChildAdapterPosition(lastChild);
768cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                int targetPos = lastChildPos * 2;
778cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                llm.scrollToPosition(targetPos);
788cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                recyclerView.measure(
798cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                        makeMeasureSpec(recyclerView.getWidth(), EXACTLY),
808cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                        makeMeasureSpec(recyclerView.getHeight(), AT_MOST));
818cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                assertThat(recyclerView.findViewHolderForAdapterPosition(targetPos),
828cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                        notNullValue());
838cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                // make sure it is still visible from top at least
848cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                int size = orientationHelper.getDecoratedMeasurement(
858cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                        recyclerView.findViewHolderForAdapterPosition(targetPos).itemView);
868cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                recyclerView.measure(
878cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                        makeMeasureSpec(recyclerView.getWidth(), EXACTLY),
888cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                        makeMeasureSpec(size + 1, EXACTLY));
898cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                recyclerView.layout(0, 0, recyclerView.getMeasuredWidth(),
908cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                        recyclerView.getMeasuredHeight());
918cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                assertThat(recyclerView.findViewHolderForAdapterPosition(targetPos),
928cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                        notNullValue());
938cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                RecyclerView.ViewHolder viewHolder =
948cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                        recyclerView.findViewHolderForAdapterPosition(targetPos);
958cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                assertThat(viewHolder, notNullValue());
968cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                Rect viewBounds = new Rect();
978cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                llm.getDecoratedBoundsWithMargins(viewHolder.itemView, viewBounds);
988cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar                Rect rvBounds = new Rect(0, 0, llm.getWidth(), llm.getHeight());
999aae13b01e2a00d892ab82677f613bcc6e380baeYigit Boyar                assertThat(rvBounds + " vs " + viewBounds, rvBounds.contains(viewBounds), is(true));
1008cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar            }
1018cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar        });
1028cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar    }
1038cf399b2e813234a1a603df3575c2dcdfa38dc9eYigit Boyar}