1/* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package android.support.v7.widget; 18 19import org.hamcrest.CoreMatchers; 20import org.junit.Test; 21import org.junit.runner.RunWith; 22import org.junit.runners.Parameterized; 23 24import android.graphics.Color; 25import android.test.suitebuilder.annotation.MediumTest; 26import android.view.View; 27import android.view.ViewGroup; 28 29import java.util.ArrayList; 30import java.util.List; 31 32import static android.support.v7.widget.LinearLayoutManager.HORIZONTAL; 33import static android.support.v7.widget.LinearLayoutManager.VERTICAL; 34import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; 35import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; 36import static org.hamcrest.MatcherAssert.assertThat; 37 38@RunWith(Parameterized.class) 39@MediumTest 40public class LinearLayoutManagerWrapContentWithAspectRatioTest 41 extends BaseWrapContentWithAspectRatioTest { 42 43 final LinearLayoutManagerTest.Config mConfig; 44 final float mRatio; 45 46 public LinearLayoutManagerWrapContentWithAspectRatioTest( 47 BaseLinearLayoutManagerTest.Config config, 48 BaseWrapContentTest.WrapContentConfig wrapContentConfig, 49 float ratio) { 50 super(wrapContentConfig); 51 mConfig = config; 52 mRatio = ratio; 53 } 54 55 @Parameterized.Parameters(name = "{0} {1} ratio:{2}") 56 public static Iterable<Object[]> data() { 57 List<Object[]> params = new ArrayList<>(); 58 for (float ratio : new float[]{.5f, 1f, 2f}) { 59 for (int orientation : new int[]{VERTICAL, HORIZONTAL}) { 60 for (boolean reverseLayout : new boolean[]{false, true}) { 61 for (boolean stackFromBottom : new boolean[]{false, true}) { 62 params.add( 63 new Object[]{ 64 new BaseLinearLayoutManagerTest.Config(orientation, 65 reverseLayout, stackFromBottom), 66 new BaseWrapContentTest.WrapContentConfig( 67 false, false), 68 ratio 69 } 70 ); 71 params.add( 72 new Object[]{ 73 new BaseLinearLayoutManagerTest.Config(orientation, 74 reverseLayout, stackFromBottom), 75 new BaseWrapContentTest.WrapContentConfig( 76 HORIZONTAL == orientation, 77 VERTICAL == orientation), 78 ratio 79 } 80 ); 81 params.add( 82 new Object[]{ 83 new BaseLinearLayoutManagerTest.Config(orientation, 84 reverseLayout, stackFromBottom), 85 new BaseWrapContentTest.WrapContentConfig( 86 VERTICAL == orientation, 87 HORIZONTAL == orientation), 88 ratio 89 } 90 ); 91 params.add( 92 new Object[]{ 93 new BaseLinearLayoutManagerTest.Config(orientation, 94 reverseLayout, stackFromBottom), 95 new BaseWrapContentTest.WrapContentConfig( 96 true, true), 97 ratio 98 } 99 ); 100 } 101 } 102 } 103 } 104 return params; 105 } 106 107 @Test 108 public void wrapContentAffectsOtherOrientation() throws Throwable { 109 TestedFrameLayout.FullControlLayoutParams 110 wrapContent = new TestedFrameLayout.FullControlLayoutParams( 111 ViewGroup.LayoutParams.WRAP_CONTENT, 112 ViewGroup.LayoutParams.WRAP_CONTENT); 113 int testOrientation = mConfig.mOrientation == VERTICAL ? HORIZONTAL : VERTICAL; 114 boolean unlimitedSize = false; 115 if (mWrapContentConfig.isUnlimitedHeight()) { 116 wrapContent.hSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); 117 unlimitedSize = testOrientation == VERTICAL; 118 } 119 if (mWrapContentConfig.isUnlimitedWidth()) { 120 wrapContent.wSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); 121 unlimitedSize |= testOrientation == HORIZONTAL; 122 } 123 124 RecyclerView.LayoutManager layoutManager = createFromConfig(); 125 BaseWrapContentTest.WrappedRecyclerView 126 recyclerView = new BaseWrapContentTest.WrappedRecyclerView(getActivity()); 127 recyclerView.setBackgroundColor(Color.rgb(0, 0, 255)); 128 recyclerView.setLayoutManager(layoutManager); 129 recyclerView.setLayoutParams(wrapContent); 130 131 AspectRatioMeasureBehavior behavior1 = new AspectRatioMeasureBehavior(10, 10, 132 WRAP_CONTENT, WRAP_CONTENT).aspectRatio(testOrientation, mRatio); 133 AspectRatioMeasureBehavior behavior2 = new AspectRatioMeasureBehavior(15, 15, 134 testOrientation == HORIZONTAL ? MATCH_PARENT : WRAP_CONTENT, 135 testOrientation == VERTICAL ? MATCH_PARENT : WRAP_CONTENT) 136 .aspectRatio(testOrientation, mRatio); 137 AspectRatioMeasureBehavior behavior3 = new AspectRatioMeasureBehavior(8, 8, 138 testOrientation == HORIZONTAL ? MATCH_PARENT : WRAP_CONTENT, 139 testOrientation == VERTICAL ? MATCH_PARENT : WRAP_CONTENT) 140 .aspectRatio(testOrientation, mRatio); 141 142 WrapContentAdapter adapter = new WrapContentAdapter( 143 behavior1, behavior2, behavior3 144 ); 145 146 recyclerView.setAdapter(adapter); 147 setRecyclerView(recyclerView); 148 recyclerView.waitUntilLayout(); 149 150 int parentDim = getSize((View) recyclerView.getParent(), testOrientation); 151 152 View itemView1 = recyclerView.findViewHolderForAdapterPosition(0).itemView; 153 assertThat("first child test size", getSize(itemView1, testOrientation), 154 CoreMatchers.is(10)); 155 assertThat("first child dependant size", getSize(itemView1, mConfig.mOrientation), 156 CoreMatchers.is(behavior1.getSecondary(10))); 157 158 View itemView2 = recyclerView.findViewHolderForAdapterPosition(1).itemView; 159 assertThat("second child test size", getSize(itemView2, testOrientation), 160 CoreMatchers.is(15)); 161 assertThat("second child dependant size", getSize(itemView2, mConfig.mOrientation), 162 CoreMatchers.is(behavior2.getSecondary(15))); 163 164 View itemView3 = recyclerView.findViewHolderForAdapterPosition(2).itemView; 165 assertThat("third child test size", getSize(itemView3, testOrientation), 166 CoreMatchers.is(15)); 167 assertThat("third child dependant size", getSize(itemView3, mConfig.mOrientation), 168 CoreMatchers.is(behavior3.getSecondary(15))); 169 170 assertThat("it should be measured only once", behavior1.measureSpecs.size(), 171 CoreMatchers.is(1)); 172 if (unlimitedSize) { 173 assertThat(behavior1.getSpec(0, testOrientation), 174 MeasureSpecMatcher.is(0, View.MeasureSpec.UNSPECIFIED)); 175 } else { 176 assertThat(behavior1.getSpec(0, testOrientation), 177 MeasureSpecMatcher.is(parentDim, View.MeasureSpec.AT_MOST)); 178 } 179 180 assertThat("it should be measured once", behavior2.measureSpecs.size(), CoreMatchers.is(1)); 181 if (unlimitedSize) { 182 assertThat(behavior2.getSpec(0, testOrientation), 183 MeasureSpecMatcher.is(0, View.MeasureSpec.UNSPECIFIED)); 184 } else { 185 assertThat(behavior2.getSpec(0, testOrientation), 186 MeasureSpecMatcher.is(parentDim, View.MeasureSpec.AT_MOST)); 187 } 188 189 assertThat("it should be measured twice", behavior3.measureSpecs.size(), 190 CoreMatchers.is(2)); 191 if (unlimitedSize) { 192 assertThat(behavior3.getSpec(0, testOrientation), 193 MeasureSpecMatcher.is(0, View.MeasureSpec.UNSPECIFIED)); 194 } else { 195 assertThat(behavior3.getSpec(0, testOrientation), 196 MeasureSpecMatcher.is(parentDim, View.MeasureSpec.AT_MOST)); 197 } 198 199 assertThat(behavior3.getSpec(1, testOrientation), 200 MeasureSpecMatcher.is(15, View.MeasureSpec.EXACTLY)); 201 final int totalScrollSize = getSize(itemView1, mConfig.mOrientation) 202 + getSize(itemView2, mConfig.mOrientation) 203 + getSize(itemView3, mConfig.mOrientation); 204 assertThat("RecyclerView should wrap its content in the scroll direction", 205 getSize(mRecyclerView, mConfig.mOrientation), CoreMatchers.is(totalScrollSize)); 206 assertThat("RecyclerView should wrap its content in the scroll direction", 207 getSize(mRecyclerView, testOrientation), CoreMatchers.is(15)); 208 } 209 210 private LinearLayoutManager createFromConfig() { 211 LinearLayoutManager llm = new LinearLayoutManager(getActivity(), mConfig.mOrientation, 212 mConfig.mReverseLayout); 213 llm.setStackFromEnd(mConfig.mStackFromEnd); 214 return llm; 215 } 216} 217