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 */ 16package android.support.percent; 17 18import android.os.Build; 19import android.support.percent.test.R; 20import android.support.v4.view.ViewCompat; 21import android.test.UiThreadTest; 22import android.test.suitebuilder.annotation.SmallTest; 23import android.view.View; 24import org.junit.Before; 25import org.junit.Test; 26 27import static android.support.percent.LayoutDirectionActions.setLayoutDirection; 28import static android.support.test.espresso.Espresso.onView; 29import static android.support.test.espresso.matcher.ViewMatchers.withId; 30import static org.junit.Assume.*; 31/** 32 * The arrangement of child views in the layout class in the default LTR (left-to-right) direction 33 * is as follows: 34 * 35 * +---------------------------------------------+ 36 * | | 37 * | TTTTTTTTTTTTTTTTTTTTT | 38 * | | 39 * | S | 40 * | S CCCCCCCCCCCCCCCCCC | 41 * | S CCCCCCCCCCCCCCCCCC | 42 * | S CCCCCCCCCCCCCCCCCC E | 43 * | S CCCCCCCCCCCCCCCCCC E | 44 * | S CCCCCCCCCCCCCCCCCC E | 45 * | CCCCCCCCCCCCCCCCCC E | 46 * | CCCCCCCCCCCCCCCCCC E | 47 * | E | 48 * | | 49 * | BBBBBBBBBBBBBBBBBBBBB | 50 * | | 51 * +---------------------------------------------+ 52 * 53 * The arrangement of child views in the layout class in the RTL (right-to-left) direction 54 * is as follows: 55 * 56 * +---------------------------------------------+ 57 * | | 58 * | TTTTTTTTTTTTTTTTTTTTT | 59 * | | 60 * | S | 61 * | CCCCCCCCCCCCCCCCCC S | 62 * | CCCCCCCCCCCCCCCCCC S | 63 * | E CCCCCCCCCCCCCCCCCC S | 64 * | E CCCCCCCCCCCCCCCCCC S | 65 * | E CCCCCCCCCCCCCCCCCC S | 66 * | E CCCCCCCCCCCCCCCCCC | 67 * | E CCCCCCCCCCCCCCCCCC | 68 * | E | 69 * | | 70 * | BBBBBBBBBBBBBBBBBBBBB | 71 * | | 72 * +---------------------------------------------+ 73 * 74 * Child views are exercising the following percent-based constraints supported by 75 * <code>PercentRelativeLayout</code>: 76 * 77 * <ul> 78 * <li>Top child (marked with T) - width, aspect ratio, top margin, start margin.</li> 79 * <li>Start child (marked with S) - height, aspect ratio, top margin, start margin.</li> 80 * <li>Bottom child (marked with B) - width, aspect ratio, bottom margin, end margin.</li> 81 * <li>Right child (marked with E) - height, aspect ratio, bottom margin, end margin.</li> 82 * <li>Center child (marked with C) - margin (all sides) from the other four children.</li> 83 * </ul> 84 * 85 * Under LTR direction (pre-v17 devices and v17+ with default direction of en-US locale) we are 86 * testing the same assertions as <code>PercentRelativeTest</code>. Under RTL direction (on v17+ 87 * devices with Espresso-powered direction switch) we are testing the reverse assertions along the 88 * X axis for all child views. 89 * 90 * Note that due to a bug in the core {@link RelativeLayout} (base class of 91 * {@link PercentRelativeLayout}) in how it treats end margin of child views on v17 devices, we are 92 * skipping all tests in this class for v17 devices. This is in line with the overall contract 93 * of percent-based layouts provided by the support library - we do not work around / fix bugs in 94 * the core classes, but rather just provide a translation layer between percentage-based values 95 * and pixel-based ones. 96 */ 97@SmallTest 98public class PercentRelativeRtlTest extends BaseInstrumentationTestCase<TestRelativeRtlActivity> { 99 private PercentRelativeLayout mPercentRelativeLayout; 100 private int mContainerWidth; 101 private int mContainerHeight; 102 103 public PercentRelativeRtlTest() { 104 super(TestRelativeRtlActivity.class); 105 } 106 107 @Before 108 public void setUp() throws Exception { 109 assumeTrue(Build.VERSION.SDK_INT != 17); 110 111 final TestRelativeRtlActivity activity = mActivityTestRule.getActivity(); 112 mPercentRelativeLayout = (PercentRelativeLayout) activity.findViewById(R.id.container); 113 mContainerWidth = mPercentRelativeLayout.getWidth(); 114 mContainerHeight = mPercentRelativeLayout.getHeight(); 115 } 116 117 private void switchToRtl() { 118 // Force the container to RTL mode 119 onView(withId(R.id.container)).perform( 120 setLayoutDirection(ViewCompat.LAYOUT_DIRECTION_RTL)); 121 122 // Force a full measure + layout pass on the container 123 mPercentRelativeLayout.measure( 124 View.MeasureSpec.makeMeasureSpec(mContainerWidth, View.MeasureSpec.EXACTLY), 125 View.MeasureSpec.makeMeasureSpec(mContainerHeight, View.MeasureSpec.EXACTLY)); 126 mPercentRelativeLayout.layout(mPercentRelativeLayout.getLeft(), 127 mPercentRelativeLayout.getTop(), mPercentRelativeLayout.getRight(), 128 mPercentRelativeLayout.getBottom()); 129 } 130 131 @Test 132 public void testTopChild() { 133 final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_top); 134 135 if (Build.VERSION.SDK_INT >= 17) { 136 switchToRtl(); 137 138 final int childRight = childToTest.getRight(); 139 assertFuzzyEquals("Child start margin as 20% of the container", 140 0.2f * mContainerWidth, mContainerWidth - childRight); 141 } else { 142 final int childLeft = childToTest.getLeft(); 143 assertFuzzyEquals("Child start margin as 20% of the container", 144 0.2f * mContainerWidth, childLeft); 145 } 146 147 final int childTop = childToTest.getTop(); 148 assertFuzzyEquals("Child top margin as 5% of the container", 149 0.05f * mContainerHeight, childTop); 150 151 final int childWidth = childToTest.getWidth(); 152 final int childHeight = childToTest.getHeight(); 153 154 assertFuzzyEquals("Child width as 50% of the container", 155 0.5f * mContainerWidth, childWidth); 156 assertFuzzyEquals("Child aspect ratio of 2000%", 157 0.05f * childWidth, childHeight); 158 } 159 160 @Test 161 public void testStartChild() { 162 final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_start); 163 164 if (Build.VERSION.SDK_INT >= 17) { 165 switchToRtl(); 166 167 final int childRight = childToTest.getRight(); 168 assertFuzzyEquals("Child start margin as 5% of the container", 169 0.05f * mContainerWidth, mContainerWidth - childRight); 170 } else { 171 final int childLeft = childToTest.getLeft(); 172 assertFuzzyEquals("Child start margin as 5% of the container", 173 0.05f * mContainerWidth, childLeft); 174 } 175 176 final int childWidth = childToTest.getWidth(); 177 final int childHeight = childToTest.getHeight(); 178 179 assertFuzzyEquals("Child height as 50% of the container", 180 0.5f * mContainerHeight, childHeight); 181 assertFuzzyEquals("Child aspect ratio of 5%", 182 0.05f * childHeight, childWidth); 183 184 final int childTop = childToTest.getTop(); 185 186 assertFuzzyEquals("Child top margin as 20% of the container", 187 0.2f * mContainerHeight, childTop); 188 } 189 190 @Test 191 public void testBottomChild() { 192 final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_bottom); 193 194 if (Build.VERSION.SDK_INT >= 17) { 195 switchToRtl(); 196 197 final int childLeft = childToTest.getLeft(); 198 assertFuzzyEquals("Child end margin as 20% of the container", 199 0.2f * mContainerWidth, childLeft); 200 } else { 201 final int childRight = childToTest.getRight(); 202 assertFuzzyEquals("Child end margin as 20% of the container", 203 0.2f * mContainerWidth, mContainerWidth - childRight); 204 } 205 206 207 final int childWidth = childToTest.getWidth(); 208 final int childHeight = childToTest.getHeight(); 209 210 assertFuzzyEquals("Child width as 40% of the container", 211 0.4f * mContainerWidth, childWidth); 212 assertFuzzyEquals("Child aspect ratio of 2000%", 213 0.05f * childWidth, childHeight); 214 215 final int childBottom = childToTest.getBottom(); 216 217 assertFuzzyEquals("Child bottom margin as 5% of the container", 218 0.05f * mContainerHeight, mContainerHeight - childBottom); 219 } 220 221 @Test 222 public void testEndChild() { 223 final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_end); 224 225 if (Build.VERSION.SDK_INT >= 17) { 226 switchToRtl(); 227 228 final int childLeft = childToTest.getLeft(); 229 assertFuzzyEquals("Child end margin as 5% of the container", 230 0.05f * mContainerWidth, childLeft); 231 } else { 232 final int childRight = childToTest.getRight(); 233 assertFuzzyEquals("Child end margin as 5% of the container", 234 0.05f * mContainerWidth, mContainerWidth - childRight); 235 } 236 237 final int childWidth = childToTest.getWidth(); 238 final int childHeight = childToTest.getHeight(); 239 240 assertFuzzyEquals("Child height as 50% of the container", 241 0.4f * mContainerHeight, childHeight); 242 assertFuzzyEquals("Child aspect ratio of 5%", 243 0.05f * childHeight, childWidth); 244 245 final int childBottom = childToTest.getBottom(); 246 247 assertFuzzyEquals("Child bottom margin as 20% of the container", 248 0.2f * mContainerHeight, mContainerHeight - childBottom); 249 } 250 251 @Test 252 public void testCenterChild() { 253 final View childToTest = mPercentRelativeLayout.findViewById(R.id.child_center); 254 255 boolean supportsRtl = Build.VERSION.SDK_INT >= 17; 256 if (supportsRtl) { 257 switchToRtl(); 258 } 259 260 final int childLeft = childToTest.getLeft(); 261 final int childTop = childToTest.getTop(); 262 final int childRight = childToTest.getRight(); 263 final int childBottom = childToTest.getBottom(); 264 265 final View leftChild = supportsRtl 266 ? mPercentRelativeLayout.findViewById(R.id.child_end) 267 : mPercentRelativeLayout.findViewById(R.id.child_start); 268 assertFuzzyEquals("Child left margin as 10% of the container", 269 leftChild.getRight() + 0.1f * mContainerWidth, childLeft); 270 271 final View topChild = mPercentRelativeLayout.findViewById(R.id.child_top); 272 assertFuzzyEquals("Child top margin as 10% of the container", 273 topChild.getBottom() + 0.1f * mContainerHeight, childTop); 274 275 final View rightChild = supportsRtl 276 ? mPercentRelativeLayout.findViewById(R.id.child_start) 277 : mPercentRelativeLayout.findViewById(R.id.child_end); 278 assertFuzzyEquals("Child right margin as 10% of the container", 279 rightChild.getLeft() - 0.1f * mContainerWidth, childRight); 280 281 final View bottomChild = mPercentRelativeLayout.findViewById(R.id.child_bottom); 282 assertFuzzyEquals("Child bottom margin as 10% of the container", 283 bottomChild.getTop() - 0.1f * mContainerHeight, childBottom); 284 } 285} 286