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