/* * Copyright (C) 2016 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.support.v7.widget; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import android.graphics.Color; import android.test.suitebuilder.annotation.MediumTest; import android.view.View; import java.util.ArrayList; import java.util.List; import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL; import static android.support.v7.widget.LinearLayoutManager.VERTICAL; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static org.hamcrest.MatcherAssert.assertThat; import static android.support.v7.widget.BaseWrapContentTest.WrapContentConfig; import static android.support.v7.widget.GridLayoutManagerTest.Config; import static org.hamcrest.CoreMatchers.*; import static android.view.View.MeasureSpec.UNSPECIFIED; import static android.view.View.MeasureSpec.AT_MOST; import static android.view.View.MeasureSpec.EXACTLY; @RunWith(Parameterized.class) @MediumTest public class GridLayoutManagerWrapContentWithAspectRatioTest extends BaseWrapContentWithAspectRatioTest { @Parameterized.Parameters(name = "{0} {1} {2}") public static List params() { List params = new ArrayList<>(); for (int orientation : new int[]{VERTICAL, HORIZONTAL}) { for (boolean reverseLayout : new boolean[]{false, true}) { for (boolean unlimitedW : new boolean[]{true, false}) { for (boolean unlimitedH : new boolean[]{true, false}) { for (int behavior1Size : new int[]{8, 10, 12}) { params.add(new Object[]{ new WrapContentConfig(unlimitedW, unlimitedH), new Config(3, orientation, reverseLayout), behavior1Size }); } } } } } return params; } private GridLayoutManagerTest.Config mConfig; private int mBehavior1Size; int mTestOrientation; boolean mUnlimited; RecyclerView.LayoutManager mLayoutManager; BaseWrapContentTest.WrappedRecyclerView mRecyclerView; OrientationHelper mHelper; public GridLayoutManagerWrapContentWithAspectRatioTest(WrapContentConfig wrapContentConfig, GridLayoutManagerTest.Config config, int behavior1Size) { super(wrapContentConfig); mConfig = config; mBehavior1Size = behavior1Size; } @Before public final void init() { TestedFrameLayout.FullControlLayoutParams lp = mWrapContentConfig.toLayoutParams(WRAP_CONTENT, WRAP_CONTENT); if (mConfig.mOrientation == VERTICAL) { mTestOrientation = HORIZONTAL; mUnlimited = lp.wSpec != null; } else { mTestOrientation = VERTICAL; mUnlimited = lp.hSpec != null; } mLayoutManager = createFromConfig(); mRecyclerView = new BaseWrapContentTest.WrappedRecyclerView(getActivity()); mHelper = OrientationHelper.createOrientationHelper( mLayoutManager, 1 - mConfig.mOrientation); mRecyclerView.setBackgroundColor(Color.rgb(0, 0, 255)); mRecyclerView.setLayoutManager(mLayoutManager); mRecyclerView.setLayoutParams(lp); } @Test public void testChildWithMultipleSpans() throws Throwable { MeasureBehavior behavior1; behavior1 = new MeasureBehavior(mBehavior1Size, mBehavior1Size, mTestOrientation == HORIZONTAL ? MATCH_PARENT : WRAP_CONTENT, mTestOrientation == VERTICAL ? MATCH_PARENT : WRAP_CONTENT); MeasureBehavior behavior2 = new MeasureBehavior( mTestOrientation == HORIZONTAL ? 30 : 10, mTestOrientation == VERTICAL ? 30 : 10, WRAP_CONTENT, WRAP_CONTENT); WrapContentAdapter adapter = new WrapContentAdapter(behavior1, behavior2); ((GridLayoutManager) mLayoutManager).setSpanSizeLookup( new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { return position == 1 ? 2 : 1; } }); mRecyclerView.setAdapter(adapter); setRecyclerView(mRecyclerView); mRecyclerView.waitUntilLayout(); final int parentSize = getSize((View) mRecyclerView.getParent(), mTestOrientation); if (mUnlimited) { assertThat(behavior1.getSpec(0, mTestOrientation), MeasureSpecMatcher.mode(UNSPECIFIED)); assertThat(behavior2.getSpec(0, mTestOrientation), MeasureSpecMatcher.mode(UNSPECIFIED)); } else { int[] borders = GridLayoutManager.calculateItemBorders(null, mConfig.mSpanCount, parentSize); assertThat(behavior1.getSpec(0, mTestOrientation), MeasureSpecMatcher.is(borders[1] - borders[0], AT_MOST)); assertThat(behavior2.getSpec(0, mTestOrientation), MeasureSpecMatcher.is(borders[3] - borders[1], AT_MOST)); } // child0 should be measured again because it measured its size as 10 assertThat(behavior1.getSpec(1, mTestOrientation), MeasureSpecMatcher.is(15, EXACTLY)); assertThat(behavior1.getSpec(1, mConfig.mOrientation), MeasureSpecMatcher.mode(UNSPECIFIED)); switch (mBehavior1Size) { case 10: assertThat(behavior1.measureSpecs.size(), is(2)); assertThat(behavior2.measureSpecs.size(), is(1)); break; case 8: assertThat(behavior2.measureSpecs.size(), is(1)); assertThat(behavior1.measureSpecs.size(), is(3)); assertThat(behavior1.getSpec(2, mTestOrientation), MeasureSpecMatcher.is(15, EXACTLY)); assertThat(behavior1.getSpec(2, mConfig.mOrientation), MeasureSpecMatcher.is(10, EXACTLY)); break; case 12: assertThat(behavior1.measureSpecs.size(), is(2)); assertThat(behavior2.measureSpecs.size(), is(2)); assertThat(behavior2.getSpec(1, mTestOrientation), MeasureSpecMatcher.is(30, AT_MOST)); assertThat(behavior2.getSpec(1, mConfig.mOrientation), MeasureSpecMatcher.is(12, EXACTLY)); break; } View child0 = mRecyclerView.getChildAt(0); assertThat(getSize(child0, mTestOrientation), is(15)); View child1 = mRecyclerView.getChildAt(1); assertThat(getSize(child1, mTestOrientation), is(30)); assertThat(mHelper.getDecoratedStart(child0), is(0)); assertThat(mHelper.getDecoratedStart(child1), is(15)); assertThat(mHelper.getDecoratedEnd(child0), is(15)); assertThat(mHelper.getDecoratedEnd(child1), is(45)); assertThat(mHelper.getDecoratedMeasurementInOther(child0), is(Math.max(10, mBehavior1Size))); assertThat(mHelper.getDecoratedMeasurementInOther(child1), is(Math.max(10, mBehavior1Size))); assertThat(getSize(mRecyclerView, mTestOrientation), is(45)); assertThat(getSize(mRecyclerView, 1 - mTestOrientation), is(Math.max(10, mBehavior1Size))); } @Test public void testChildWithMatchParentInOtherDirection() throws Throwable { MeasureBehavior behavior1; behavior1 = new MeasureBehavior(mBehavior1Size, mBehavior1Size, mTestOrientation == HORIZONTAL ? MATCH_PARENT : WRAP_CONTENT, mTestOrientation == VERTICAL ? MATCH_PARENT : WRAP_CONTENT); MeasureBehavior behavior2 = new MeasureBehavior( mTestOrientation == HORIZONTAL ? 15 : 10, mTestOrientation == VERTICAL ? 15 : 10, WRAP_CONTENT, WRAP_CONTENT); WrapContentAdapter adapter = new WrapContentAdapter(behavior1, behavior2); mRecyclerView.setAdapter(adapter); setRecyclerView(mRecyclerView); mRecyclerView.waitUntilLayout(); final int parentSize = getSize((View) mRecyclerView.getParent(), mTestOrientation); if (mUnlimited) { assertThat(behavior1.getSpec(0, mTestOrientation), MeasureSpecMatcher.mode(UNSPECIFIED)); assertThat(behavior2.getSpec(0, mTestOrientation), MeasureSpecMatcher.mode(UNSPECIFIED)); } else { int[] borders = GridLayoutManager.calculateItemBorders(null, mConfig.mSpanCount, parentSize); assertThat(behavior1.getSpec(0, mTestOrientation), MeasureSpecMatcher.is(borders[1] - borders[0], AT_MOST)); assertThat(behavior2.getSpec(0, mTestOrientation), MeasureSpecMatcher.is(borders[2] - borders[1], AT_MOST)); } // child0 should be measured again because it measured its size as 10 assertThat(behavior1.getSpec(1, mTestOrientation), MeasureSpecMatcher.is(15, EXACTLY)); assertThat(behavior1.getSpec(1, mConfig.mOrientation), MeasureSpecMatcher.mode(UNSPECIFIED)); switch (mBehavior1Size) { case 10: assertThat(behavior1.measureSpecs.size(), is(2)); assertThat(behavior2.measureSpecs.size(), is(1)); break; case 8: assertThat(behavior2.measureSpecs.size(), is(1)); assertThat(behavior1.measureSpecs.size(), is(3)); assertThat(behavior1.getSpec(2, mTestOrientation), MeasureSpecMatcher.is(15, EXACTLY)); assertThat(behavior1.getSpec(2, mConfig.mOrientation), MeasureSpecMatcher.is(10, EXACTLY)); break; case 12: assertThat(behavior1.measureSpecs.size(), is(2)); assertThat(behavior2.measureSpecs.size(), is(2)); assertThat(behavior2.getSpec(1, mTestOrientation), MeasureSpecMatcher.is(15, AT_MOST)); assertThat(behavior2.getSpec(1, mConfig.mOrientation), MeasureSpecMatcher.is(12, EXACTLY)); break; } View child0 = mRecyclerView.getChildAt(0); assertThat(getSize(child0, mTestOrientation), is(15)); View child1 = mRecyclerView.getChildAt(1); assertThat(getSize(child1, mTestOrientation), is(15)); assertThat(mHelper.getDecoratedStart(child0), is(0)); assertThat(mHelper.getDecoratedStart(child1), is(15)); assertThat(mHelper.getDecoratedEnd(child0), is(15)); assertThat(mHelper.getDecoratedEnd(child1), is(30)); assertThat(mHelper.getDecoratedMeasurementInOther(child0), is(Math.max(10, mBehavior1Size))); assertThat(mHelper.getDecoratedMeasurementInOther(child1), is(Math.max(10, mBehavior1Size))); assertThat(getSize(mRecyclerView, mTestOrientation), is(45)); assertThat(getSize(mRecyclerView, 1 - mTestOrientation), is(Math.max(10, mBehavior1Size))); } @Test public void testAllChildrenWrapContentInOtherDirection() throws Throwable { MeasureBehavior behavior1; behavior1 = new MeasureBehavior(mBehavior1Size, mBehavior1Size, WRAP_CONTENT, WRAP_CONTENT); MeasureBehavior behavior2 = new MeasureBehavior( mTestOrientation == HORIZONTAL ? 15 : 10, mTestOrientation == VERTICAL ? 15 : 10, WRAP_CONTENT, WRAP_CONTENT); WrapContentAdapter adapter = new WrapContentAdapter(behavior1, behavior2); mRecyclerView.setAdapter(adapter); setRecyclerView(mRecyclerView); mRecyclerView.waitUntilLayout(); final int parentSize = getSize((View) mRecyclerView.getParent(), mTestOrientation); if (mUnlimited) { assertThat(behavior1.getSpec(0, mTestOrientation), MeasureSpecMatcher.mode(UNSPECIFIED)); assertThat(behavior2.getSpec(0, mTestOrientation), MeasureSpecMatcher.mode(UNSPECIFIED)); } else { int[] borders = GridLayoutManager.calculateItemBorders(null, mConfig.mSpanCount, parentSize); assertThat(behavior1.getSpec(0, mTestOrientation), MeasureSpecMatcher.is(borders[1] - borders[0], AT_MOST)); assertThat(behavior2.getSpec(0, mTestOrientation), MeasureSpecMatcher.is(borders[2] - borders[1], AT_MOST)); } switch (mBehavior1Size) { case 10: assertThat(behavior1.measureSpecs.size(), is(1)); assertThat(behavior2.measureSpecs.size(), is(1)); break; case 8: assertThat(behavior2.measureSpecs.size(), is(1)); assertThat(behavior1.measureSpecs.size(), is(2)); assertThat(behavior1.getSpec(1, mTestOrientation), MeasureSpecMatcher.is(15, AT_MOST)); assertThat(behavior1.getSpec(1, mConfig.mOrientation), MeasureSpecMatcher.is(10, EXACTLY)); break; case 12: assertThat(behavior1.measureSpecs.size(), is(1)); assertThat(behavior2.measureSpecs.size(), is(2)); assertThat(behavior2.getSpec(1, mTestOrientation), MeasureSpecMatcher.is(15, AT_MOST)); assertThat(behavior2.getSpec(1, mConfig.mOrientation), MeasureSpecMatcher.is(12, EXACTLY)); break; } View child0 = mRecyclerView.getChildAt(0); assertThat(getSize(child0, mTestOrientation), is(mBehavior1Size)); View child1 = mRecyclerView.getChildAt(1); assertThat(getSize(child1, mTestOrientation), is(15)); assertThat(mHelper.getDecoratedStart(child0), is(0)); assertThat(mHelper.getDecoratedStart(child1), is(15)); assertThat(mHelper.getDecoratedEnd(child0), is(mBehavior1Size)); assertThat(mHelper.getDecoratedEnd(child1), is(30)); assertThat(mHelper.getDecoratedMeasurementInOther(child0), is(Math.max(10, mBehavior1Size))); assertThat(mHelper.getDecoratedMeasurementInOther(child1), is(Math.max(10, mBehavior1Size))); assertThat(getSize(mRecyclerView, mTestOrientation), is(45)); assertThat(getSize(mRecyclerView, 1 - mTestOrientation), is(Math.max(10, mBehavior1Size))); } private RecyclerView.LayoutManager createFromConfig() { return new GridLayoutManager(getActivity(), mConfig.mSpanCount, mConfig.mOrientation, mConfig.mReverseLayout); } }