1 /* 2 * Copyright (C) 2008 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 17 package android.widget.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.junit.Assert.fail; 25 26 import android.annotation.ColorInt; 27 import android.annotation.Nullable; 28 import android.app.Activity; 29 import android.app.Instrumentation; 30 import android.content.Context; 31 import android.content.res.Resources; 32 import android.graphics.Color; 33 import android.graphics.Rect; 34 import android.graphics.drawable.Drawable; 35 import android.support.test.InstrumentationRegistry; 36 import android.support.test.annotation.UiThreadTest; 37 import android.support.test.filters.MediumTest; 38 import android.support.test.rule.ActivityTestRule; 39 import android.support.test.runner.AndroidJUnit4; 40 import android.test.ViewAsserts; 41 import android.util.AttributeSet; 42 import android.util.Xml; 43 import android.view.Gravity; 44 import android.view.View; 45 import android.view.View.MeasureSpec; 46 import android.view.ViewGroup; 47 import android.view.ViewTreeObserver; 48 import android.widget.AbsoluteLayout; 49 import android.widget.LinearLayout; 50 import android.widget.LinearLayout.LayoutParams; 51 import android.widget.ListView; 52 import android.widget.TextView; 53 import android.widget.cts.util.TestUtils; 54 55 import com.android.compatibility.common.util.WidgetTestUtils; 56 57 import org.junit.Before; 58 import org.junit.Rule; 59 import org.junit.Test; 60 import org.junit.runner.RunWith; 61 import org.xmlpull.v1.XmlPullParser; 62 63 import java.util.concurrent.CountDownLatch; 64 import java.util.concurrent.TimeUnit; 65 66 /** 67 * Test {@link LinearLayout}. 68 */ 69 @MediumTest 70 @RunWith(AndroidJUnit4.class) 71 public class LinearLayoutTest { 72 private Instrumentation mInstrumentation; 73 private Activity mActivity; 74 75 @Rule 76 public ActivityTestRule<LinearLayoutCtsActivity> mActivityRule = 77 new ActivityTestRule<>(LinearLayoutCtsActivity.class); 78 79 @Before setup()80 public void setup() { 81 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 82 mActivity = mActivityRule.getActivity(); 83 } 84 85 @Test testConstructor()86 public void testConstructor() { 87 new LinearLayout(mActivity); 88 89 new LinearLayout(mActivity, null); 90 91 XmlPullParser parser = mActivity.getResources().getXml(R.layout.linearlayout_layout); 92 AttributeSet attrs = Xml.asAttributeSet(parser); 93 new LinearLayout(mActivity, attrs); 94 } 95 96 @Test(expected=NullPointerException.class) testConstructorNullContext()97 public void testConstructorNullContext() { 98 new LinearLayout(null, null); 99 } 100 101 @UiThreadTest 102 @Test testAccessBaselineAligned()103 public void testAccessBaselineAligned() { 104 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_empty); 105 parent.setBaselineAligned(true); 106 assertTrue(parent.isBaselineAligned()); 107 108 parent.setBaselineAligned(false); 109 assertFalse(parent.isBaselineAligned()); 110 111 // android:baselineAligned="false" in LinearLayout weightsum 112 parent = (LinearLayout) mActivity.findViewById(R.id.linear_weightsum); 113 assertFalse(parent.isBaselineAligned()); 114 115 // default mBaselineAligned is true. 116 parent = (LinearLayout) mActivity.findViewById(R.id.linear_horizontal); 117 assertTrue(parent.isBaselineAligned()); 118 119 // default mBaselineAligned is true. 120 // Only applicable if {@link #mOrientation} is horizontal 121 parent = (LinearLayout) mActivity.findViewById(R.id.linear_vertical); 122 assertTrue(parent.isBaselineAligned()); 123 } 124 125 @UiThreadTest 126 @Test testGetBaseline()127 public void testGetBaseline() { 128 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_empty); 129 130 ListView lv1 = new ListView(mActivity); 131 parent.addView(lv1); 132 assertEquals(-1, parent.getBaseline()); 133 134 ListView lv2 = new ListView(mActivity); 135 parent.addView(lv2); 136 parent.setBaselineAlignedChildIndex(1); 137 try { 138 parent.getBaseline(); 139 fail("LinearLayout.getBaseline() should throw exception here."); 140 } catch (RuntimeException e) { 141 } 142 143 ListView lv3 = new MockListView(mActivity); 144 parent.addView(lv3); 145 parent.setBaselineAlignedChildIndex(2); 146 assertEquals(lv3.getBaseline(), parent.getBaseline()); 147 } 148 149 @UiThreadTest 150 @Test testAccessBaselineAlignedChildIndex()151 public void testAccessBaselineAlignedChildIndex() { 152 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_empty); 153 154 // set BaselineAlignedChildIndex 155 ListView lv1 = new ListView(mActivity); 156 ListView lv2 = new ListView(mActivity); 157 ListView lv3 = new ListView(mActivity); 158 parent.addView(lv1); 159 parent.addView(lv2); 160 parent.addView(lv3); 161 parent.setBaselineAlignedChildIndex(1); 162 assertEquals(1, parent.getBaselineAlignedChildIndex()); 163 164 parent.setBaselineAlignedChildIndex(2); 165 assertEquals(2, parent.getBaselineAlignedChildIndex()); 166 167 try { 168 parent.setBaselineAlignedChildIndex(-1); 169 fail("LinearLayout should throw IllegalArgumentException here."); 170 } catch (IllegalArgumentException e) { 171 } 172 try { 173 parent.setBaselineAlignedChildIndex(3); 174 fail("LinearLayout should throw IllegalArgumentException here."); 175 } catch (IllegalArgumentException e) { 176 } 177 178 parent = (LinearLayout) mActivity.findViewById(R.id.linear_baseline_aligned_child_index); 179 assertEquals(1, parent.getBaselineAlignedChildIndex()); 180 } 181 182 /** 183 * weightsum is a horizontal LinearLayout. There are three children in it. 184 */ 185 @Test testAccessWeightSum()186 public void testAccessWeightSum() { 187 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_weightsum); 188 TextView weight02 = (TextView) parent.findViewById(R.id.weight_0_2); 189 TextView weight05 = (TextView) parent.findViewById(R.id.weight_0_5); 190 TextView weight03 = (TextView) parent.findViewById(R.id.weight_0_3); 191 192 assertNotNull(parent); 193 assertNotNull(weight02); 194 assertNotNull(weight05); 195 assertNotNull(weight03); 196 197 assertEquals(mActivity.getResources().getString(R.string.horizontal_text_1), 198 weight02.getText().toString()); 199 assertEquals(mActivity.getResources().getString(R.string.horizontal_text_2), 200 weight05.getText().toString()); 201 assertEquals(mActivity.getResources().getString(R.string.horizontal_text_3), 202 weight03.getText().toString()); 203 204 assertEquals(LinearLayout.HORIZONTAL, parent.getOrientation()); 205 assertEquals(1.0f, parent.getWeightSum(), 0.0f); 206 207 int parentWidth = parent.getWidth(); 208 assertEquals(Math.ceil(parentWidth * 0.2), weight02.getWidth(), 1.0); 209 assertEquals(Math.ceil(parentWidth * 0.5), weight05.getWidth(), 1.0); 210 assertEquals(Math.ceil(parentWidth * 0.3), weight03.getWidth(), 1.0); 211 } 212 213 @UiThreadTest 214 @Test testWeightDistribution()215 public void testWeightDistribution() { 216 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_empty); 217 218 for (int i = 0; i < 3; i++) { 219 parent.addView(new View(mActivity), new LayoutParams(0, 0, 1)); 220 } 221 222 int size = 100; 223 int spec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.EXACTLY); 224 225 for (int i = 0; i < 3; i++) { 226 View child = parent.getChildAt(i); 227 LayoutParams lp = (LayoutParams) child.getLayoutParams(); 228 lp.height = 0; 229 lp.width = LayoutParams.MATCH_PARENT; 230 child.setLayoutParams(lp); 231 } 232 parent.setOrientation(LinearLayout.VERTICAL); 233 parent.measure(spec, spec); 234 parent.layout(0, 0, size, size); 235 assertEquals(100, parent.getWidth()); 236 assertEquals(100, parent.getChildAt(0).getWidth()); 237 assertEquals(100, parent.getChildAt(1).getWidth()); 238 assertEquals(100, parent.getChildAt(2).getWidth()); 239 assertEquals(100, parent.getHeight()); 240 assertEquals(33, parent.getChildAt(0).getHeight()); 241 assertEquals(33, parent.getChildAt(1).getHeight()); 242 assertEquals(34, parent.getChildAt(2).getHeight()); 243 244 for (int i = 0; i < 3; i++) { 245 View child = parent.getChildAt(i); 246 LayoutParams lp = (LayoutParams) child.getLayoutParams(); 247 lp.height = LayoutParams.MATCH_PARENT; 248 lp.width = 0; 249 child.setLayoutParams(lp); 250 } 251 parent.setOrientation(LinearLayout.HORIZONTAL); 252 parent.measure(spec, spec); 253 parent.layout(0, 0, size, size); 254 assertEquals(100, parent.getWidth()); 255 assertEquals(33, parent.getChildAt(0).getWidth()); 256 assertEquals(33, parent.getChildAt(1).getWidth()); 257 assertEquals(34, parent.getChildAt(2).getWidth()); 258 assertEquals(100, parent.getHeight()); 259 assertEquals(100, parent.getChildAt(0).getHeight()); 260 assertEquals(100, parent.getChildAt(1).getHeight()); 261 assertEquals(100, parent.getChildAt(2).getHeight()); 262 } 263 264 @UiThreadTest 265 @Test testGenerateLayoutParams()266 public void testGenerateLayoutParams() { 267 ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(320, 240); 268 MockLinearLayout parent = (MockLinearLayout) mActivity.findViewById(R.id.linear_custom); 269 LayoutParams layoutParams1 = parent.generateLayoutParams(lp); 270 assertEquals(320, layoutParams1.width); 271 assertEquals(240, layoutParams1.height); 272 } 273 274 @UiThreadTest 275 @Test testCheckLayoutParams()276 public void testCheckLayoutParams() { 277 MockLinearLayout parent = (MockLinearLayout) mActivity.findViewById(R.id.linear_custom); 278 279 ViewGroup.LayoutParams params = new AbsoluteLayout.LayoutParams(240, 320, 0, 0); 280 assertFalse(parent.checkLayoutParams(params)); 281 282 params = new LinearLayout.LayoutParams(240, 320); 283 assertTrue(parent.checkLayoutParams(params)); 284 } 285 286 @UiThreadTest 287 @Test testGenerateDefaultLayoutParams()288 public void testGenerateDefaultLayoutParams() { 289 MockLinearLayout parent = (MockLinearLayout) mActivity.findViewById(R.id.linear_custom); 290 291 parent.setOrientation(LinearLayout.HORIZONTAL); 292 ViewGroup.LayoutParams param = parent.generateDefaultLayoutParams(); 293 assertNotNull(param); 294 assertTrue(param instanceof LinearLayout.LayoutParams); 295 assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, param.width); 296 assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, param.height); 297 298 parent.setOrientation(LinearLayout.VERTICAL); 299 param = parent.generateDefaultLayoutParams(); 300 assertNotNull(param); 301 assertTrue(param instanceof LinearLayout.LayoutParams); 302 assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, param.width); 303 assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, param.height); 304 305 parent.setOrientation(-1); 306 assertNull(parent.generateDefaultLayoutParams()); 307 } 308 309 @UiThreadTest 310 @Test testGenerateLayoutParamsFromMarginParams()311 public void testGenerateLayoutParamsFromMarginParams() { 312 MockLinearLayout parent = (MockLinearLayout) mActivity.findViewById(R.id.linear_custom); 313 314 ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(3, 5); 315 lp.leftMargin = 1; 316 lp.topMargin = 2; 317 lp.rightMargin = 3; 318 lp.bottomMargin = 4; 319 LinearLayout.LayoutParams generated = parent.generateLayoutParams(lp); 320 assertNotNull(generated); 321 assertEquals(3, generated.width); 322 assertEquals(5, generated.height); 323 324 assertEquals(1, generated.leftMargin); 325 assertEquals(2, generated.topMargin); 326 assertEquals(3, generated.rightMargin); 327 assertEquals(4, generated.bottomMargin); 328 } 329 330 /** 331 * layout of horizontal LinearLayout. 332 * ---------------------------------------------------- 333 * | ------------ | | | 334 * | | top view | | --------------- | | 335 * | | | | | center view | | --------------- | 336 * | ------------ | | | | | bottom view | | 337 * | | --------------- | | | | 338 * | parent | | --------------- | 339 * ---------------------------------------------------- 340 */ 341 @Test testLayoutHorizontal()342 public void testLayoutHorizontal() { 343 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_horizontal); 344 TextView topView = (TextView) mActivity.findViewById(R.id.gravity_top); 345 TextView centerView = (TextView) mActivity.findViewById(R.id.gravity_center_vertical); 346 TextView bottomView = (TextView) mActivity.findViewById(R.id.gravity_bottom); 347 348 assertNotNull(parent); 349 assertNotNull(topView); 350 assertNotNull(centerView); 351 assertNotNull(bottomView); 352 353 assertEquals(mActivity.getResources().getString(R.string.horizontal_text_1), 354 topView.getText().toString()); 355 assertEquals(mActivity.getResources().getString(R.string.horizontal_text_2), 356 centerView.getText().toString()); 357 assertEquals(mActivity.getResources().getString(R.string.horizontal_text_3), 358 bottomView.getText().toString()); 359 360 assertEquals(LinearLayout.HORIZONTAL, parent.getOrientation()); 361 362 ViewAsserts.assertTopAligned(parent, topView); 363 ViewAsserts.assertVerticalCenterAligned(parent, centerView); 364 ViewAsserts.assertBottomAligned(parent, bottomView); 365 366 assertEquals(0, topView.getTop()); 367 assertEquals(topView.getHeight(), topView.getBottom()); 368 assertEquals(0, topView.getLeft()); 369 assertEquals(centerView.getLeft(), topView.getRight()); 370 371 int offset = (parent.getHeight() - centerView.getHeight()) / 2; 372 assertEquals(offset, centerView.getTop()); 373 assertEquals(offset + centerView.getHeight(), centerView.getBottom()); 374 assertEquals(topView.getRight(), centerView.getLeft()); 375 assertEquals(bottomView.getLeft(), centerView.getRight()); 376 377 assertEquals(parent.getHeight() - bottomView.getHeight(), bottomView.getTop()); 378 assertEquals(parent.getHeight(), bottomView.getBottom()); 379 assertEquals(centerView.getRight(), bottomView.getLeft()); 380 assertEquals(parent.getWidth(), bottomView.getRight()); 381 } 382 383 /** 384 * layout of vertical LinearLayout. 385 * ----------------------------------- 386 * | ------------- | 387 * | | left view | | 388 * | ------------- | 389 * | - - - - - - - - - - - - - - - - | 390 * | --------------- | 391 * | | center view | | 392 * | --------------- | 393 * | - - - - - - - - - - - - - - - - | 394 * | -------------- | 395 * | parent | right view | | 396 * | -------------- | 397 * ----------------------------------- 398 */ 399 @Test testLayoutVertical()400 public void testLayoutVertical() { 401 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_vertical); 402 TextView leftView = (TextView) mActivity.findViewById(R.id.gravity_left); 403 TextView centerView = (TextView) mActivity.findViewById(R.id.gravity_center_horizontal); 404 TextView rightView = (TextView) mActivity.findViewById(R.id.gravity_right); 405 406 assertNotNull(parent); 407 assertNotNull(leftView); 408 assertNotNull(centerView); 409 assertNotNull(rightView); 410 411 assertEquals(mActivity.getResources().getString(R.string.vertical_text_1), 412 leftView.getText().toString()); 413 assertEquals(mActivity.getResources().getString(R.string.vertical_text_2), 414 centerView.getText().toString()); 415 assertEquals(mActivity.getResources().getString(R.string.vertical_text_3), 416 rightView.getText().toString()); 417 418 assertEquals(LinearLayout.VERTICAL, parent.getOrientation()); 419 420 ViewAsserts.assertLeftAligned(parent, leftView); 421 ViewAsserts.assertHorizontalCenterAligned(parent, centerView); 422 ViewAsserts.assertRightAligned(parent, rightView); 423 424 assertEquals(0, leftView.getTop()); 425 assertEquals(centerView.getTop(), leftView.getBottom()); 426 assertEquals(0, leftView.getLeft()); 427 assertEquals(leftView.getWidth(), leftView.getRight()); 428 429 int offset = (parent.getWidth() - centerView.getWidth()) / 2; 430 assertEquals(leftView.getBottom(), centerView.getTop()); 431 assertEquals(rightView.getTop(), centerView.getBottom()); 432 assertEquals(offset, centerView.getLeft()); 433 assertEquals(offset + centerView.getWidth(), centerView.getRight()); 434 435 assertEquals(centerView.getBottom(), rightView.getTop()); 436 assertEquals(parent.getHeight(), rightView.getBottom()); 437 assertEquals(parent.getWidth() - rightView.getWidth(), rightView.getLeft()); 438 assertEquals(parent.getWidth(), rightView.getRight()); 439 } 440 441 @Test testVerticalCenterGravityOnHorizontalLayout()442 public void testVerticalCenterGravityOnHorizontalLayout() throws Throwable { 443 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_weightsum); 444 TextView leftView = (TextView) parent.findViewById(R.id.weight_0_2); 445 TextView centerView = (TextView) parent.findViewById(R.id.weight_0_5); 446 TextView rightView = (TextView) parent.findViewById(R.id.weight_0_3); 447 448 mActivityRule.runOnUiThread(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR)); 449 mInstrumentation.waitForIdleSync(); 450 451 int originalLeftViewLeft = leftView.getLeft(); 452 int originalLeftViewRight = leftView.getRight(); 453 int originalCenterViewLeft = centerView.getLeft(); 454 int originalCenterViewRight = centerView.getRight(); 455 int originalRightViewLeft = rightView.getLeft(); 456 int originalRightViewRight = rightView.getRight(); 457 458 mActivityRule.runOnUiThread(() -> parent.setVerticalGravity(Gravity.CENTER_VERTICAL)); 459 mInstrumentation.waitForIdleSync(); 460 461 assertEquals(Gravity.CENTER_VERTICAL, parent.getGravity() & Gravity.VERTICAL_GRAVITY_MASK); 462 463 ViewAsserts.assertVerticalCenterAligned(parent, leftView); 464 ViewAsserts.assertVerticalCenterAligned(parent, centerView); 465 ViewAsserts.assertVerticalCenterAligned(parent, rightView); 466 467 final int parentHeight = parent.getHeight(); 468 469 int verticalOffset = (parentHeight - leftView.getHeight()) / 2; 470 assertEquals(verticalOffset, leftView.getTop()); 471 assertEquals(verticalOffset + leftView.getHeight(), leftView.getBottom()); 472 assertEquals(originalLeftViewLeft, leftView.getLeft()); 473 assertEquals(originalLeftViewRight, leftView.getRight()); 474 475 verticalOffset = (parentHeight - centerView.getHeight()) / 2; 476 assertEquals(verticalOffset, centerView.getTop()); 477 assertEquals(verticalOffset + centerView.getHeight(), centerView.getBottom()); 478 assertEquals(originalCenterViewLeft, centerView.getLeft()); 479 assertEquals(originalCenterViewRight, centerView.getRight()); 480 481 verticalOffset = (parentHeight - rightView.getHeight()) / 2; 482 assertEquals(verticalOffset, rightView.getTop()); 483 assertEquals(verticalOffset + rightView.getHeight(), rightView.getBottom()); 484 assertEquals(originalRightViewLeft, rightView.getLeft()); 485 assertEquals(originalRightViewRight, rightView.getRight()); 486 } 487 488 @Test testBottomGravityOnHorizontalLayout()489 public void testBottomGravityOnHorizontalLayout() throws Throwable { 490 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_weightsum); 491 TextView leftView = (TextView) parent.findViewById(R.id.weight_0_2); 492 TextView centerView = (TextView) parent.findViewById(R.id.weight_0_5); 493 TextView rightView = (TextView) parent.findViewById(R.id.weight_0_3); 494 495 mActivityRule.runOnUiThread(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR)); 496 mInstrumentation.waitForIdleSync(); 497 498 int originalLeftViewLeft = leftView.getLeft(); 499 int originalLeftViewRight = leftView.getRight(); 500 int originalCenterViewLeft = centerView.getLeft(); 501 int originalCenterViewRight = centerView.getRight(); 502 int originalRightViewLeft = rightView.getLeft(); 503 int originalRightViewRight = rightView.getRight(); 504 505 mActivityRule.runOnUiThread(() -> parent.setVerticalGravity(Gravity.BOTTOM)); 506 mInstrumentation.waitForIdleSync(); 507 508 assertEquals(Gravity.BOTTOM, parent.getGravity() & Gravity.VERTICAL_GRAVITY_MASK); 509 510 ViewAsserts.assertBottomAligned(parent, leftView); 511 ViewAsserts.assertBottomAligned(parent, centerView); 512 ViewAsserts.assertBottomAligned(parent, rightView); 513 514 final int parentHeight = parent.getHeight(); 515 516 assertEquals(parentHeight - leftView.getHeight(), leftView.getTop()); 517 assertEquals(parentHeight, leftView.getBottom()); 518 assertEquals(originalLeftViewLeft, leftView.getLeft()); 519 assertEquals(originalLeftViewRight, leftView.getRight()); 520 521 assertEquals(parentHeight - centerView.getHeight(), centerView.getTop()); 522 assertEquals(parentHeight, centerView.getBottom()); 523 assertEquals(originalCenterViewLeft, centerView.getLeft()); 524 assertEquals(originalCenterViewRight, centerView.getRight()); 525 526 assertEquals(parentHeight - rightView.getHeight(), rightView.getTop()); 527 assertEquals(parentHeight, rightView.getBottom()); 528 assertEquals(originalRightViewLeft, rightView.getLeft()); 529 assertEquals(originalRightViewRight, rightView.getRight()); 530 } 531 532 @Test testHorizontalCenterGravityOnVerticalLayout()533 public void testHorizontalCenterGravityOnVerticalLayout() throws Throwable { 534 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_weightsum_vertical); 535 TextView topView = (TextView) parent.findViewById(R.id.weight_0_1); 536 TextView centerView = (TextView) parent.findViewById(R.id.weight_0_4); 537 TextView bottomView = (TextView) parent.findViewById(R.id.weight_0_5); 538 539 mActivityRule.runOnUiThread(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR)); 540 mInstrumentation.waitForIdleSync(); 541 542 final int parentWidth = parent.getHeight(); 543 544 int originalTopViewTop = topView.getTop(); 545 int originalTopViewBottom = topView.getBottom(); 546 int originalCenterViewTop = centerView.getTop(); 547 int originalCenterViewBottom = centerView.getBottom(); 548 int originalBottomViewTop = bottomView.getTop(); 549 int originalBottomViewBottom = bottomView.getBottom(); 550 551 mActivityRule.runOnUiThread( 552 () -> parent.setHorizontalGravity(Gravity.CENTER_HORIZONTAL)); 553 mInstrumentation.waitForIdleSync(); 554 555 assertEquals(Gravity.CENTER_HORIZONTAL, 556 parent.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK); 557 558 ViewAsserts.assertHorizontalCenterAligned(parent, topView); 559 ViewAsserts.assertHorizontalCenterAligned(parent, centerView); 560 ViewAsserts.assertHorizontalCenterAligned(parent, bottomView); 561 562 int horizontalOffset = (parentWidth - topView.getWidth()) / 2; 563 assertEquals(originalTopViewTop, topView.getTop()); 564 assertEquals(originalTopViewBottom, topView.getBottom()); 565 assertEquals(horizontalOffset, topView.getLeft()); 566 assertEquals(horizontalOffset + topView.getWidth(), topView.getRight()); 567 568 horizontalOffset = (parentWidth - centerView.getWidth()) / 2; 569 assertEquals(originalCenterViewTop, centerView.getTop()); 570 assertEquals(originalCenterViewBottom, centerView.getBottom()); 571 assertEquals(horizontalOffset, centerView.getLeft()); 572 assertEquals(horizontalOffset + centerView.getWidth(), centerView.getRight()); 573 574 horizontalOffset = (parentWidth - bottomView.getWidth()) / 2; 575 assertEquals(originalBottomViewTop, bottomView.getTop()); 576 assertEquals(originalBottomViewBottom, bottomView.getBottom()); 577 assertEquals(horizontalOffset, bottomView.getLeft()); 578 assertEquals(horizontalOffset + bottomView.getWidth(), bottomView.getRight()); 579 } 580 581 @Test testRightGravityOnVerticalLayout()582 public void testRightGravityOnVerticalLayout() throws Throwable { 583 LinearLayout parent = (LinearLayout) mActivity.findViewById(R.id.linear_weightsum_vertical); 584 TextView topView = (TextView) parent.findViewById(R.id.weight_0_1); 585 TextView centerView = (TextView) parent.findViewById(R.id.weight_0_4); 586 TextView bottomView = (TextView) parent.findViewById(R.id.weight_0_5); 587 588 mActivityRule.runOnUiThread(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR)); 589 mInstrumentation.waitForIdleSync(); 590 591 final int parentWidth = parent.getHeight(); 592 593 int originalTopViewTop = topView.getTop(); 594 int originalTopViewBottom = topView.getBottom(); 595 int originalCenterViewTop = centerView.getTop(); 596 int originalCenterViewBottom = centerView.getBottom(); 597 int originalBottomViewTop = bottomView.getTop(); 598 int originalBottomViewBottom = bottomView.getBottom(); 599 600 mActivityRule.runOnUiThread(() -> parent.setHorizontalGravity(Gravity.RIGHT)); 601 mInstrumentation.waitForIdleSync(); 602 603 assertEquals(Gravity.RIGHT, parent.getGravity() & Gravity.HORIZONTAL_GRAVITY_MASK); 604 605 ViewAsserts.assertRightAligned(parent, topView); 606 ViewAsserts.assertRightAligned(parent, centerView); 607 ViewAsserts.assertRightAligned(parent, bottomView); 608 609 assertEquals(originalTopViewTop, topView.getTop()); 610 assertEquals(originalTopViewBottom, topView.getBottom()); 611 assertEquals(parentWidth - topView.getWidth(), topView.getLeft()); 612 assertEquals(parentWidth, topView.getRight()); 613 614 assertEquals(originalCenterViewTop, centerView.getTop()); 615 assertEquals(originalCenterViewBottom, centerView.getBottom()); 616 assertEquals(parentWidth - centerView.getWidth(), centerView.getLeft()); 617 assertEquals(parentWidth, centerView.getRight()); 618 619 assertEquals(originalBottomViewTop, bottomView.getTop()); 620 assertEquals(originalBottomViewBottom, bottomView.getBottom()); 621 assertEquals(parentWidth - bottomView.getWidth(), bottomView.getLeft()); 622 assertEquals(parentWidth, bottomView.getRight()); 623 } 624 verifyBounds(final ViewGroup viewGroup, final View view, final CountDownLatch countDownLatch, final int left, final int top, final int width, final int height)625 private void verifyBounds(final ViewGroup viewGroup, final View view, 626 final CountDownLatch countDownLatch, final int left, final int top, 627 final int width, final int height) { 628 viewGroup.getViewTreeObserver().addOnPreDrawListener( 629 new ViewTreeObserver.OnPreDrawListener() { 630 @Override 631 public boolean onPreDraw() { 632 assertEquals(left, view.getLeft()); 633 assertEquals(top, view.getTop()); 634 assertEquals(width, view.getWidth()); 635 assertEquals(height, view.getHeight()); 636 countDownLatch.countDown(); 637 viewGroup.getViewTreeObserver().removeOnPreDrawListener(this); 638 return true; 639 } 640 }); 641 } 642 643 @Test testVisibilityAffectsLayout()644 public void testVisibilityAffectsLayout() throws Throwable { 645 // Toggling view visibility between GONE/VISIBLE can affect the position of 646 // other children in that container. This test verifies that these changes 647 // on the first child of a LinearLayout affects the position of a second child 648 final int childWidth = 100; 649 final int childHeight = 200; 650 final LinearLayout parent = new LinearLayout(mActivity); 651 ViewGroup.LayoutParams parentParams = new ViewGroup.LayoutParams( 652 ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 653 parent.setLayoutParams(parentParams); 654 final View child1 = new View(mActivity); 655 child1.setBackgroundColor(Color.GREEN); 656 ViewGroup.LayoutParams childParams = new ViewGroup.LayoutParams(childWidth, childHeight); 657 child1.setLayoutParams(childParams); 658 final View child2 = new View(mActivity); 659 child2.setBackgroundColor(Color.RED); 660 childParams = new ViewGroup.LayoutParams(childWidth, childHeight); 661 child2.setLayoutParams(childParams); 662 final ViewGroup viewGroup = (ViewGroup) mActivity.findViewById(R.id.linearlayout_root); 663 664 final CountDownLatch countDownLatch1 = new CountDownLatch(1); 665 mActivityRule.runOnUiThread(() -> { 666 viewGroup.removeAllViews(); 667 viewGroup.addView(parent); 668 parent.addView(child1); 669 parent.addView(child2); 670 verifyBounds(viewGroup, child1, countDownLatch1, 0, 0, childWidth, childHeight); 671 verifyBounds(viewGroup, child2, countDownLatch1, 672 childWidth, 0, childWidth, childHeight); 673 }); 674 try { 675 assertTrue(countDownLatch1.await(500, TimeUnit.MILLISECONDS)); 676 } catch (InterruptedException ie) { 677 fail(ie.getMessage()); 678 } 679 680 final CountDownLatch countDownLatch2 = new CountDownLatch(1); 681 mActivityRule.runOnUiThread(() -> { 682 child1.setVisibility(View.GONE); 683 verifyBounds(viewGroup, child2, countDownLatch2, 0, 0, childWidth, childHeight); 684 }); 685 try { 686 assertTrue(countDownLatch2.await(500, TimeUnit.MILLISECONDS)); 687 } catch (InterruptedException ie) { 688 fail(ie.getMessage()); 689 } 690 691 final CountDownLatch countDownLatch3 = new CountDownLatch(2); 692 mActivityRule.runOnUiThread(() -> { 693 child1.setVisibility(View.VISIBLE); 694 verifyBounds(viewGroup, child1, countDownLatch3, 0, 0, childWidth, childHeight); 695 verifyBounds(viewGroup, child2, countDownLatch3, 696 childWidth, 0, childWidth, childHeight); 697 }); 698 try { 699 assertTrue(countDownLatch3.await(500, TimeUnit.MILLISECONDS)); 700 } catch (InterruptedException ie) { 701 fail(ie.getMessage()); 702 } 703 } 704 verifyVisualsOfVerticalLayoutWithDivider(LinearLayout parent, int expectedDividerPositionMask, int expectedDividerSize, @ColorInt int expectedDividerColor, int expectedDividerPadding)705 private void verifyVisualsOfVerticalLayoutWithDivider(LinearLayout parent, 706 int expectedDividerPositionMask, 707 int expectedDividerSize, @ColorInt int expectedDividerColor, 708 int expectedDividerPadding) { 709 final int parentWidth = parent.getWidth(); 710 final int parentHeight = parent.getHeight(); 711 712 final boolean expectingTopDivider = 713 (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_BEGINNING) != 0; 714 final boolean expectingMiddleDivider = 715 (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_MIDDLE) != 0; 716 final boolean expectingBottomDivider = 717 (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_END) != 0; 718 final int expectedDividerCount = (expectingTopDivider ? 1 : 0) 719 + (expectingMiddleDivider ? 1 : 0) + (expectingBottomDivider ? 1 : 0); 720 721 final int expectedChildHeight = 722 (parentHeight - expectedDividerCount * expectedDividerSize) / 2; 723 724 final int expectedTopChildTop = expectingTopDivider ? expectedDividerSize : 0; 725 TestUtils.assertRegionPixelsOfColor("Region of first child is blue", parent, 726 new Rect(0, expectedTopChildTop, parentWidth, 727 expectedTopChildTop + expectedChildHeight), 728 Color.BLUE, 1, true); 729 730 final int expectedBottomChildBottom = 731 expectingBottomDivider ? parentHeight - expectedDividerSize : parentHeight; 732 TestUtils.assertRegionPixelsOfColor("Region of second child is green", parent, 733 new Rect(0, expectedBottomChildBottom - expectedChildHeight, parentWidth, 734 expectedBottomChildBottom), 735 Color.GREEN, 1, true); 736 737 if (expectedDividerSize == 0) { 738 return; 739 } 740 741 // Do we expect top divider? 742 if (expectingTopDivider) { 743 TestUtils.assertRegionPixelsOfColor( 744 "Region of top divider is " + TestUtils.formatColorToHex(expectedDividerColor), 745 parent, 746 new Rect(expectedDividerPadding, 0, parentWidth - expectedDividerPadding, 747 expectedDividerSize), 748 expectedDividerColor, 1, true); 749 TestUtils.assertRegionPixelsOfColor("Region of left padding of top divider is yellow", 750 parent, 751 new Rect(0, 0, expectedDividerPadding, expectedDividerSize), 752 Color.YELLOW, 1, true); 753 TestUtils.assertRegionPixelsOfColor("Region of right padding of top divider is yellow", 754 parent, 755 new Rect(parentWidth - expectedDividerPadding, 0, parentWidth, 756 expectedDividerSize), 757 Color.YELLOW, 1, true); 758 } 759 760 // Do we expect middle divider? 761 if (expectingMiddleDivider) { 762 final int expectedMiddleDividerTop = expectedTopChildTop + expectedChildHeight; 763 TestUtils.assertRegionPixelsOfColor( 764 "Region of middle divider is " + 765 TestUtils.formatColorToHex(expectedDividerColor), 766 parent, 767 new Rect(expectedDividerPadding, expectedMiddleDividerTop, 768 parentWidth - expectedDividerPadding, 769 expectedMiddleDividerTop + expectedDividerSize), 770 expectedDividerColor, 1, true); 771 TestUtils.assertRegionPixelsOfColor( 772 "Region of left padding of middle divider is yellow", 773 parent, 774 new Rect(0, expectedMiddleDividerTop, expectedDividerPadding, 775 expectedMiddleDividerTop + expectedDividerSize), 776 Color.YELLOW, 1, true); 777 TestUtils.assertRegionPixelsOfColor( 778 "Region of right padding of middle divider is yellow", 779 parent, 780 new Rect(parentWidth - expectedDividerPadding, expectedMiddleDividerTop, 781 parentWidth, expectedMiddleDividerTop + expectedDividerSize), 782 Color.YELLOW, 1, true); 783 } 784 785 // Do we expect bottom divider? 786 if (expectingBottomDivider) { 787 final int expectedBottomDividerTop = expectedBottomChildBottom; 788 TestUtils.assertRegionPixelsOfColor( 789 "Region of bottom divider is " + 790 TestUtils.formatColorToHex(expectedDividerColor), 791 parent, 792 new Rect(expectedDividerPadding, expectedBottomDividerTop, 793 parentWidth - expectedDividerPadding, 794 expectedBottomDividerTop + expectedDividerSize), 795 expectedDividerColor, 1, true); 796 TestUtils.assertRegionPixelsOfColor( 797 "Region of left padding of bottom divider is yellow", 798 parent, 799 new Rect(0, expectedBottomDividerTop, expectedDividerPadding, 800 expectedBottomDividerTop + expectedDividerSize), 801 Color.YELLOW, 1, true); 802 TestUtils.assertRegionPixelsOfColor( 803 "Region of right padding of bottom divider is yellow", 804 parent, 805 new Rect(parentWidth - expectedDividerPadding, expectedBottomDividerTop, 806 parentWidth, expectedBottomDividerTop + expectedDividerSize), 807 Color.YELLOW, 1, true); 808 } 809 } 810 811 /** 812 * layout of vertical LinearLayout. 813 * ----------------------------------- 814 * | ------------------------------- | 815 * | | child1 | | 816 * | ------------------------------- | 817 * | - - - - - - divider - - - - - - | 818 * | ------------------------------- | 819 * | | child2 | | 820 * | ------------------------------- | 821 * ----------------------------------- 822 * 823 * Parent is filled with yellow color. Child 1 is filled with green and child 2 is filled 824 * with blue. Divider is red at the beginning. Throughout this method we reconfigure the 825 * visibility, drawable and paddings of the divider and verify the overall visuals of the 826 * container. 827 */ 828 @Test testDividersInVerticalLayout()829 public void testDividersInVerticalLayout() throws Throwable { 830 final LinearLayout parent = 831 (LinearLayout) mActivity.findViewById(R.id.linear_vertical_with_divider); 832 833 final Resources res = mActivity.getResources(); 834 final int dividerSize = res.getDimensionPixelSize(R.dimen.linear_layout_divider_size); 835 final int dividerPadding = res.getDimensionPixelSize(R.dimen.linear_layout_divider_padding); 836 837 assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE, parent.getShowDividers()); 838 assertEquals(dividerPadding, parent.getDividerPadding()); 839 final Drawable dividerDrawable = parent.getDividerDrawable(); 840 TestUtils.assertAllPixelsOfColor("Divider is red", dividerDrawable, 841 dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(), 842 false, Color.RED, 1, true); 843 844 // Test the initial visuals of the entire parent 845 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 846 dividerSize, Color.RED, dividerPadding); 847 848 // Change the divider to magenta 849 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 850 () -> parent.setDividerDrawable( 851 mActivity.getDrawable(R.drawable.linear_layout_divider_magenta))); 852 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 853 dividerSize, Color.MAGENTA, dividerPadding); 854 855 // Change the divider to null (no divider effectively) 856 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 857 () -> parent.setDividerDrawable(null)); 858 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 859 0, Color.TRANSPARENT, 0); 860 861 // Change the divider back to red 862 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 863 () -> parent.setDividerDrawable( 864 mActivity.getDrawable(R.drawable.linear_layout_divider_red))); 865 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 866 dividerSize, Color.RED, dividerPadding); 867 868 // Change the padding to half the original size 869 final int halfPadding = dividerPadding / 2; 870 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 871 () -> parent.setDividerPadding(halfPadding)); 872 assertEquals(halfPadding, parent.getDividerPadding()); 873 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 874 dividerSize, Color.RED, halfPadding); 875 876 // Change the padding to twice the original size 877 final int doublePadding = dividerPadding * 2; 878 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 879 () -> parent.setDividerPadding(doublePadding)); 880 assertEquals(doublePadding, parent.getDividerPadding()); 881 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 882 dividerSize, Color.RED, doublePadding); 883 884 // And back to the original padding 885 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 886 () -> parent.setDividerPadding(dividerPadding)); 887 assertEquals(dividerPadding, parent.getDividerPadding()); 888 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 889 dividerSize, Color.RED, dividerPadding); 890 891 // Set show dividers to NONE (no divider effectively) 892 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 893 () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE)); 894 assertEquals(LinearLayout.SHOW_DIVIDER_NONE, parent.getShowDividers()); 895 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_NONE, 896 0, Color.TRANSPARENT, 0); 897 898 // Show only top divider 899 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 900 () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING)); 901 assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING, parent.getShowDividers()); 902 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_BEGINNING, 903 dividerSize, Color.RED, dividerPadding); 904 905 // Show only bottom divider 906 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 907 () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_END)); 908 assertEquals(LinearLayout.SHOW_DIVIDER_END, parent.getShowDividers()); 909 verifyVisualsOfVerticalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_END, 910 dividerSize, Color.RED, dividerPadding); 911 912 // Show top and bottom dividers 913 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 914 () -> parent.setShowDividers( 915 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END)); 916 assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END, 917 parent.getShowDividers()); 918 verifyVisualsOfVerticalLayoutWithDivider(parent, 919 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END, 920 dividerSize, Color.RED, dividerPadding); 921 922 // Show top and middle dividers 923 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 924 () -> parent.setShowDividers( 925 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE)); 926 assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE, 927 parent.getShowDividers()); 928 verifyVisualsOfVerticalLayoutWithDivider(parent, 929 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE, 930 dividerSize, Color.RED, dividerPadding); 931 932 // Show middle and bottom dividers 933 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 934 () -> parent.setShowDividers( 935 LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END)); 936 assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END, 937 parent.getShowDividers()); 938 verifyVisualsOfVerticalLayoutWithDivider(parent, 939 LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END, 940 dividerSize, Color.RED, dividerPadding); 941 942 // Show top, middle and bottom dividers 943 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 944 () -> parent.setShowDividers( 945 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE 946 | LinearLayout.SHOW_DIVIDER_END)); 947 assertEquals( 948 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE 949 | LinearLayout.SHOW_DIVIDER_END, 950 parent.getShowDividers()); 951 verifyVisualsOfVerticalLayoutWithDivider(parent, 952 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE 953 | LinearLayout.SHOW_DIVIDER_END, 954 dividerSize, Color.RED, dividerPadding); 955 } 956 verifyVisualsOfHorizontalLayoutWithDivider(LinearLayout parent, int expectedDividerPositionMask, int expectedDividerSize, @ColorInt int expectedDividerColor, int expectedDividerPadding)957 private void verifyVisualsOfHorizontalLayoutWithDivider(LinearLayout parent, 958 int expectedDividerPositionMask, 959 int expectedDividerSize, @ColorInt int expectedDividerColor, 960 int expectedDividerPadding) { 961 final int parentWidth = parent.getWidth(); 962 final int parentHeight = parent.getHeight(); 963 964 final boolean expectingLeftDivider = 965 (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_BEGINNING) != 0; 966 final boolean expectingMiddleDivider = 967 (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_MIDDLE) != 0; 968 final boolean expectingRightDivider = 969 (expectedDividerPositionMask & LinearLayout.SHOW_DIVIDER_END) != 0; 970 final int expectedDividerCount = (expectingLeftDivider ? 1 : 0) 971 + (expectingMiddleDivider ? 1 : 0) + (expectingRightDivider ? 1 : 0); 972 973 final int expectedChildWidth = 974 (parentWidth - expectedDividerCount * expectedDividerSize) / 2; 975 976 final int expectedLeftChildLeft = expectingLeftDivider ? expectedDividerSize : 0; 977 TestUtils.assertRegionPixelsOfColor("Region of first child is blue", parent, 978 new Rect(expectedLeftChildLeft, 0, 979 expectedLeftChildLeft + expectedChildWidth, parentHeight), 980 Color.BLUE, 1, true); 981 982 final int expectedRightChildRight = 983 expectingRightDivider ? parentWidth - expectedDividerSize : parentWidth; 984 TestUtils.assertRegionPixelsOfColor("Region of second child is green", parent, 985 new Rect(expectedRightChildRight - expectedChildWidth, 0, expectedRightChildRight, 986 parentHeight), 987 Color.GREEN, 1, true); 988 989 if (expectedDividerSize == 0) { 990 return; 991 } 992 993 // Do we expect left divider? 994 if (expectingLeftDivider) { 995 TestUtils.assertRegionPixelsOfColor( 996 "Region of left divider is " + TestUtils.formatColorToHex(expectedDividerColor), 997 parent, 998 new Rect(0, expectedDividerPadding, expectedDividerSize, 999 parentHeight - expectedDividerPadding), 1000 expectedDividerColor, 1, true); 1001 TestUtils.assertRegionPixelsOfColor( 1002 "Region of top padding of left divider is yellow", 1003 parent, 1004 new Rect(0, 0, expectedDividerSize, expectedDividerPadding), 1005 Color.YELLOW, 1, true); 1006 TestUtils.assertRegionPixelsOfColor( 1007 "Region of bottom padding of left divider is yellow", 1008 parent, 1009 new Rect(0, parentHeight - expectedDividerPadding, expectedDividerSize, 1010 parentHeight), 1011 Color.YELLOW, 1, true); 1012 } 1013 1014 // Do we expect middle divider? 1015 if (expectingMiddleDivider) { 1016 final int expectedMiddleDividerLeft = expectedLeftChildLeft + expectedChildWidth; 1017 TestUtils.assertRegionPixelsOfColor( 1018 "Region of middle divider is " + 1019 TestUtils.formatColorToHex(expectedDividerColor), 1020 parent, 1021 new Rect(expectedMiddleDividerLeft, expectedDividerPadding, 1022 expectedMiddleDividerLeft + expectedDividerSize, 1023 parentHeight - expectedDividerPadding), 1024 expectedDividerColor, 1, true); 1025 TestUtils.assertRegionPixelsOfColor( 1026 "Region of top padding of middle divider is yellow", 1027 parent, 1028 new Rect(expectedMiddleDividerLeft, 0, 1029 expectedMiddleDividerLeft + expectedDividerSize, 1030 expectedDividerPadding), 1031 Color.YELLOW, 1, true); 1032 TestUtils.assertRegionPixelsOfColor( 1033 "Region of bottom padding of middle divider is yellow", 1034 parent, 1035 new Rect(expectedMiddleDividerLeft, parentHeight - expectedDividerPadding, 1036 expectedMiddleDividerLeft + expectedDividerSize, parentHeight), 1037 Color.YELLOW, 1, true); 1038 } 1039 1040 // Do we expect right divider? 1041 if (expectingRightDivider) { 1042 final int expectedRightDividerLeft = expectedRightChildRight; 1043 TestUtils.assertRegionPixelsOfColor( 1044 "Region of right divider is " + 1045 TestUtils.formatColorToHex(expectedDividerColor), 1046 parent, 1047 new Rect(expectedRightDividerLeft, expectedDividerPadding, 1048 expectedRightDividerLeft + expectedDividerSize, 1049 parentHeight - expectedDividerPadding), 1050 expectedDividerColor, 1, true); 1051 TestUtils.assertRegionPixelsOfColor( 1052 "Region of top padding of right divider is yellow", 1053 parent, 1054 new Rect(expectedRightDividerLeft, 0, 1055 expectedRightDividerLeft + expectedDividerSize, 1056 expectedDividerPadding), 1057 Color.YELLOW, 1, true); 1058 TestUtils.assertRegionPixelsOfColor( 1059 "Region of bottom padding of right divider is yellow", 1060 parent, 1061 new Rect(expectedRightDividerLeft, parentHeight - expectedDividerPadding, 1062 expectedRightDividerLeft + expectedDividerSize, parentHeight), 1063 Color.YELLOW, 1, true); 1064 } 1065 } 1066 1067 /** 1068 * layout of horizontal LinearLayout. 1069 * ----------------------------------- 1070 * | ------------ | ------------- | 1071 * | | | | | | 1072 * | | | d | | | 1073 * | | | i | | | 1074 * | | | v | | | 1075 * | | child1 | i | child2 | | 1076 * | | | d | | | 1077 * | | | e | | | 1078 * | | | r | | | 1079 * | | | | | | 1080 * | ------------ | ------------- | 1081 * ----------------------------------- 1082 * 1083 * Parent is filled with yellow color. Child 1 is filled with green and child 2 is filled 1084 * with blue. Divider is red at the beginning. Throughout this method we reconfigure the 1085 * visibility, drawable and paddings of the divider and verify the overall visuals of the 1086 * container. 1087 */ 1088 @Test testDividersInHorizontalLayout()1089 public void testDividersInHorizontalLayout() throws Throwable { 1090 final LinearLayout parent = 1091 (LinearLayout) mActivity.findViewById(R.id.linear_horizontal_with_divider); 1092 1093 mActivityRule.runOnUiThread(() -> parent.setLayoutDirection(View.LAYOUT_DIRECTION_LTR)); 1094 mInstrumentation.waitForIdleSync(); 1095 1096 final Resources res = mActivity.getResources(); 1097 final int dividerSize = res.getDimensionPixelSize(R.dimen.linear_layout_divider_size); 1098 final int dividerPadding = res.getDimensionPixelSize(R.dimen.linear_layout_divider_padding); 1099 1100 assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE, parent.getShowDividers()); 1101 assertEquals(dividerPadding, parent.getDividerPadding()); 1102 final Drawable dividerDrawable = parent.getDividerDrawable(); 1103 TestUtils.assertAllPixelsOfColor("Divider is red", dividerDrawable, 1104 dividerDrawable.getIntrinsicWidth(), dividerDrawable.getIntrinsicHeight(), 1105 false, Color.RED, 1, true); 1106 1107 // Test the initial visuals of the entire parent 1108 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 1109 dividerSize, Color.RED, dividerPadding); 1110 1111 // Change the divider to magenta 1112 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1113 () -> parent.setDividerDrawable( 1114 mActivity.getDrawable(R.drawable.linear_layout_divider_magenta))); 1115 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 1116 dividerSize, Color.MAGENTA, dividerPadding); 1117 1118 // Change the divider to null (no divider effectively) 1119 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1120 () -> parent.setDividerDrawable(null)); 1121 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 1122 0, Color.TRANSPARENT, 0); 1123 1124 // Change the divider back to red 1125 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1126 () -> parent.setDividerDrawable( 1127 mActivity.getDrawable(R.drawable.linear_layout_divider_red))); 1128 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 1129 dividerSize, Color.RED, dividerPadding); 1130 1131 // Change the padding to half the original size 1132 final int halfPadding = dividerPadding / 2; 1133 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1134 () -> parent.setDividerPadding(halfPadding)); 1135 assertEquals(halfPadding, parent.getDividerPadding()); 1136 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 1137 dividerSize, Color.RED, halfPadding); 1138 1139 // Change the padding to twice the original size 1140 final int doublePadding = dividerPadding * 2; 1141 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1142 () -> parent.setDividerPadding(doublePadding)); 1143 assertEquals(doublePadding, parent.getDividerPadding()); 1144 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 1145 dividerSize, Color.RED, doublePadding); 1146 1147 // And back to the original padding 1148 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1149 () -> parent.setDividerPadding(dividerPadding)); 1150 assertEquals(dividerPadding, parent.getDividerPadding()); 1151 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_MIDDLE, 1152 dividerSize, Color.RED, dividerPadding); 1153 1154 // Set show dividers to NONE (no divider effectively) 1155 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1156 () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_NONE)); 1157 assertEquals(LinearLayout.SHOW_DIVIDER_NONE, parent.getShowDividers()); 1158 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_NONE, 1159 0, Color.TRANSPARENT, 0); 1160 1161 // Show only left divider 1162 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1163 () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING)); 1164 assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING, parent.getShowDividers()); 1165 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_BEGINNING, 1166 dividerSize, Color.RED, dividerPadding); 1167 1168 // Show only right divider 1169 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1170 () -> parent.setShowDividers(LinearLayout.SHOW_DIVIDER_END)); 1171 assertEquals(LinearLayout.SHOW_DIVIDER_END, parent.getShowDividers()); 1172 verifyVisualsOfHorizontalLayoutWithDivider(parent, LinearLayout.SHOW_DIVIDER_END, 1173 dividerSize, Color.RED, dividerPadding); 1174 1175 // Show left and right dividers 1176 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1177 () -> parent.setShowDividers( 1178 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END)); 1179 assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END, 1180 parent.getShowDividers()); 1181 verifyVisualsOfHorizontalLayoutWithDivider(parent, 1182 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_END, 1183 dividerSize, Color.RED, dividerPadding); 1184 1185 // Show left and middle dividers 1186 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1187 () -> parent.setShowDividers( 1188 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE)); 1189 assertEquals(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE, 1190 parent.getShowDividers()); 1191 verifyVisualsOfHorizontalLayoutWithDivider(parent, 1192 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE, 1193 dividerSize, Color.RED, dividerPadding); 1194 1195 // Show middle and right dividers 1196 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1197 () -> parent.setShowDividers( 1198 LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END)); 1199 assertEquals(LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END, 1200 parent.getShowDividers()); 1201 verifyVisualsOfHorizontalLayoutWithDivider(parent, 1202 LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END, 1203 dividerSize, Color.RED, dividerPadding); 1204 1205 // Show left, middle and right dividers 1206 WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, parent, 1207 () -> parent.setShowDividers( 1208 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE 1209 | LinearLayout.SHOW_DIVIDER_END)); 1210 assertEquals( 1211 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE 1212 | LinearLayout.SHOW_DIVIDER_END, 1213 parent.getShowDividers()); 1214 verifyVisualsOfHorizontalLayoutWithDivider(parent, 1215 LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE 1216 | LinearLayout.SHOW_DIVIDER_END, 1217 dividerSize, Color.RED, dividerPadding); 1218 } 1219 1220 private class MockListView extends ListView { 1221 private final static int DEFAULT_CHILD_BASE_LINE = 1; 1222 MockListView(Context context)1223 public MockListView(Context context) { 1224 super(context); 1225 } 1226 getBaseline()1227 public int getBaseline() { 1228 return DEFAULT_CHILD_BASE_LINE; 1229 } 1230 } 1231 1232 /** 1233 * Add MockLinearLayout to help for testing protected methods in LinearLayout. 1234 * Because we can not access protected methods in LinearLayout directly, we have to 1235 * extends from it and override protected methods so that we can access them in 1236 * our test codes. 1237 */ 1238 public static class MockLinearLayout extends LinearLayout { MockLinearLayout(Context c)1239 public MockLinearLayout(Context c) { 1240 super(c); 1241 } 1242 MockLinearLayout(Context context, @Nullable AttributeSet attrs)1243 public MockLinearLayout(Context context, @Nullable AttributeSet attrs) { 1244 super(context, attrs); 1245 } 1246 1247 @Override checkLayoutParams(ViewGroup.LayoutParams p)1248 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 1249 return super.checkLayoutParams(p); 1250 } 1251 1252 @Override generateDefaultLayoutParams()1253 protected LinearLayout.LayoutParams generateDefaultLayoutParams() { 1254 return super.generateDefaultLayoutParams(); 1255 } 1256 1257 @Override generateLayoutParams(ViewGroup.LayoutParams p)1258 protected LinearLayout.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 1259 return super.generateLayoutParams(p); 1260 } 1261 } 1262 } 1263