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 org.xmlpull.v1.XmlPullParser; 20 import org.xmlpull.v1.XmlPullParserException; 21 22 import android.app.Activity; 23 import android.app.Instrumentation; 24 import android.content.Context; 25 import android.content.res.ColorStateList; 26 import android.cts.util.PollingCheck; 27 import android.cts.util.WidgetTestUtils; 28 import android.graphics.Canvas; 29 import android.graphics.Color; 30 import android.graphics.ColorFilter; 31 import android.graphics.PorterDuff; 32 import android.graphics.Rect; 33 import android.graphics.Region; 34 import android.graphics.drawable.BitmapDrawable; 35 import android.graphics.drawable.Drawable; 36 import android.test.ActivityInstrumentationTestCase2; 37 import android.util.AttributeSet; 38 import android.util.Xml; 39 import android.view.Gravity; 40 import android.view.View; 41 import android.view.ViewGroup; 42 import android.widget.Button; 43 import android.widget.FrameLayout; 44 import android.widget.FrameLayout.LayoutParams; 45 import android.widget.LinearLayout; 46 import android.widget.TextView; 47 import android.widget.cts.R; 48 import android.widget.cts.util.ViewTestUtils; 49 50 import java.io.IOException; 51 52 public class FrameLayoutTest extends ActivityInstrumentationTestCase2<FrameLayoutCtsActivity> { 53 private Activity mActivity; 54 private Instrumentation mInstrumentation; 55 private FrameLayout mFrameLayout; 56 57 public FrameLayoutTest() { 58 super("android.widget.cts", FrameLayoutCtsActivity.class); 59 } 60 61 @Override 62 protected void setUp() throws Exception { 63 super.setUp(); 64 65 mActivity = getActivity(); 66 mInstrumentation = getInstrumentation(); 67 mFrameLayout = (FrameLayout) mActivity.findViewById(R.id.framelayout); 68 assertNotNull(mActivity); 69 assertNotNull(mInstrumentation); 70 assertNotNull(mFrameLayout); 71 } 72 73 public void testConstructor() throws XmlPullParserException, IOException { 74 AttributeSet attrs = getAttributeSet(); 75 76 new FrameLayout(mActivity); 77 new FrameLayout(mActivity, attrs); 78 new FrameLayout(mActivity, attrs, 0); 79 } 80 81 public void testSetForegroundGravity() { 82 final BitmapDrawable foreground 83 = (BitmapDrawable) mActivity.getResources().getDrawable(R.drawable.size_48x48); 84 compareScaledPixels(48, foreground.getIntrinsicHeight()); 85 compareScaledPixels(48, foreground.getIntrinsicWidth()); 86 assertTrue(mFrameLayout.getHeight() > foreground.getIntrinsicHeight()); 87 assertTrue(mFrameLayout.getWidth() > foreground.getIntrinsicWidth()); 88 assertNull(mFrameLayout.getForeground()); 89 90 ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mFrameLayout, 91 () -> mFrameLayout.setForeground(foreground)); 92 assertSame(foreground, mFrameLayout.getForeground()); 93 // check the default gravity FILL, it completely fills its container 94 assertTrue(foreground.isVisible()); 95 final Rect rect = foreground.getBounds(); 96 // foreground has been stretched 97 new PollingCheck() { 98 @Override 99 protected boolean check() { 100 return mFrameLayout.getHeight() == rect.bottom - rect.top; 101 } 102 }.run(); 103 assertEquals(mFrameLayout.getWidth(), rect.right - rect.left); 104 105 // should get a new foreground again, because former foreground has been stretched 106 final BitmapDrawable newForeground = 107 (BitmapDrawable) mActivity.getResources().getDrawable(R.drawable.size_48x48); 108 compareScaledPixels(48, newForeground.getIntrinsicHeight()); 109 compareScaledPixels(48, newForeground.getIntrinsicWidth()); 110 assertTrue(mFrameLayout.getHeight() > newForeground.getIntrinsicHeight()); 111 assertTrue(mFrameLayout.getWidth() > foreground.getIntrinsicWidth()); 112 113 ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mFrameLayout, () -> { 114 mFrameLayout.setForeground(newForeground); 115 mFrameLayout.setForegroundGravity(Gravity.CENTER); 116 }); 117 mInstrumentation.waitForIdleSync(); 118 assertSame(newForeground, mFrameLayout.getForeground()); 119 assertTrue(newForeground.isVisible()); 120 Rect rect2 = newForeground.getBounds(); 121 // not changing its size 122 assertEquals(foreground.getIntrinsicHeight(), rect2.bottom - rect2.top); 123 assertEquals(foreground.getIntrinsicWidth(), rect2.right - rect2.left); 124 assertCenterAligned(mFrameLayout, newForeground); 125 } 126 127 public void testGatherTransparentRegion() { 128 final LinearLayout container = 129 (LinearLayout) mActivity.findViewById(R.id.framelayout_container); 130 final Drawable foreground = mActivity.getResources().getDrawable(R.drawable.size_48x48); 131 ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mFrameLayout, () -> { 132 mFrameLayout.setForeground(foreground); 133 mFrameLayout.setForegroundGravity(Gravity.CENTER); 134 }); 135 mInstrumentation.waitForIdleSync(); 136 Region region = new Region(foreground.getBounds()); 137 assertTrue(mFrameLayout.gatherTransparentRegion(region)); 138 139 ViewTestUtils.runOnMainAndDrawSync(mInstrumentation, mFrameLayout, 140 () -> container.requestTransparentRegion(mFrameLayout)); 141 mInstrumentation.waitForIdleSync(); 142 region = new Region(foreground.getBounds()); 143 assertTrue(mFrameLayout.gatherTransparentRegion(region)); 144 } 145 146 public void testAccessMeasureAllChildren() { 147 final FrameLayout frameLayout 148 = (FrameLayout) mActivity.findViewById(R.id.framelayout_measureall); 149 assertFalse(frameLayout.getConsiderGoneChildrenWhenMeasuring()); 150 151 // text view and button are VISIBLE, they should be measured 152 final TextView textView = (TextView) frameLayout.findViewById(R.id.framelayout_textview); 153 compareScaledPixels(30, textView.getMeasuredHeight()); 154 compareScaledPixels(60, textView.getMeasuredWidth()); 155 assertEquals(textView.getMeasuredHeight(), frameLayout.getMeasuredHeight()); 156 assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth()); 157 158 // measureAll is false and text view is GONE, text view will NOT be measured 159 mActivity.runOnUiThread(() -> { 160 textView.setVisibility(View.GONE); 161 frameLayout.requestLayout(); 162 }); 163 mInstrumentation.waitForIdleSync(); 164 assertFalse(frameLayout.getConsiderGoneChildrenWhenMeasuring()); 165 Button button = (Button) frameLayout.findViewById(R.id.framelayout_button); 166 compareScaledPixels(15, button.getMeasuredHeight()); 167 compareScaledPixels(50, button.getMeasuredWidth()); 168 assertEquals(button.getMeasuredHeight(), frameLayout.getMeasuredHeight()); 169 assertEquals(button.getMeasuredWidth(), frameLayout.getMeasuredWidth()); 170 171 // measureAll is true and text view is GONE, text view will be measured 172 mActivity.runOnUiThread(() -> { 173 frameLayout.setMeasureAllChildren(true); 174 frameLayout.requestLayout(); 175 }); 176 mInstrumentation.waitForIdleSync(); 177 assertTrue(frameLayout.getConsiderGoneChildrenWhenMeasuring()); 178 assertEquals(textView.getMeasuredHeight(), frameLayout.getMeasuredHeight()); 179 assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth()); 180 } 181 182 /** 183 * Helper method to compare expected pixels, scaled to device density, with actual 184 */ 185 private void compareScaledPixels(int expected, int actual) { 186 WidgetTestUtils.assertScaledPixels(expected, actual, getActivity()); 187 } 188 189 public void testGenerateLayoutParams1() { 190 MyFrameLayout myFrameLayout = new MyFrameLayout(mActivity); 191 ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 192 ViewGroup.LayoutParams.WRAP_CONTENT); 193 194 ViewGroup.LayoutParams params = myFrameLayout.generateLayoutParams(p); 195 assertNotNull(params); 196 assertTrue(params instanceof FrameLayout.LayoutParams); 197 assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, params.width); 198 assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, params.height); 199 } 200 201 public void testGenerateLayoutParams2() throws XmlPullParserException, IOException { 202 AttributeSet attrs = getAttributeSet(); 203 204 FrameLayout.LayoutParams params = mFrameLayout.generateLayoutParams(attrs); 205 assertNotNull(params); 206 assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, params.width); 207 assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, params.height); 208 assertEquals(Gravity.BOTTOM, params.gravity); 209 } 210 211 public void testCheckLayoutParams() { 212 MyFrameLayout myFrameLayout = new MyFrameLayout(mActivity); 213 assertFalse(myFrameLayout.checkLayoutParams(null)); 214 215 int width = 120; 216 int height = 80; 217 ViewGroup.LayoutParams params1 = new ViewGroup.LayoutParams(width, height); 218 assertFalse(myFrameLayout.checkLayoutParams(params1)); 219 220 FrameLayout.LayoutParams params2 = new FrameLayout.LayoutParams(width, height); 221 assertTrue(myFrameLayout.checkLayoutParams(params2)); 222 } 223 224 public void testGenerateLayoutParamsFromMarginParams() { 225 MyFrameLayout myFrameLayout = new MyFrameLayout(mActivity); 226 ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(3, 5); 227 lp.leftMargin = 1; 228 lp.topMargin = 2; 229 lp.rightMargin = 3; 230 lp.bottomMargin = 4; 231 LayoutParams generated = (LayoutParams) myFrameLayout.generateLayoutParams(lp); 232 assertNotNull(generated); 233 assertEquals(3, generated.width); 234 assertEquals(5, generated.height); 235 236 assertEquals(1, generated.leftMargin); 237 assertEquals(2, generated.topMargin); 238 assertEquals(3, generated.rightMargin); 239 assertEquals(4, generated.bottomMargin); 240 } 241 242 public void testDrawableStateChanged() { 243 // drawableStateChanged() is implementation details, do NOT test 244 } 245 246 public void testGenerateDefaultLayoutParams() { 247 MyFrameLayout frameLayout = new MyFrameLayout(mActivity); 248 FrameLayout.LayoutParams params = frameLayout.generateDefaultLayoutParams(); 249 250 assertNotNull(params); 251 assertEquals(LayoutParams.MATCH_PARENT, params.width); 252 assertEquals(LayoutParams.MATCH_PARENT, params.height); 253 } 254 255 public void testOnLayout() { 256 // onLayout() is implementation details, do NOT test 257 } 258 259 public void testOnMeasure() { 260 // onMeasure() is implementation details, do NOT test 261 } 262 263 public void testOnSizeChanged() { 264 // onSizeChanged() is implementation details, do NOT test 265 } 266 267 public void testVerifyDrawable() { 268 MyFrameLayout myFrameLayout = new MyFrameLayout(mActivity); 269 270 Drawable drawable = mActivity.getResources().getDrawable(R.drawable.scenery); 271 myFrameLayout.setForeground(drawable); 272 assertTrue(myFrameLayout.verifyDrawable(drawable)); 273 274 drawable = mActivity.getResources().getDrawable(R.drawable.black); 275 assertFalse(myFrameLayout.verifyDrawable(drawable)); 276 277 assertTrue(myFrameLayout.verifyDrawable(null)); 278 } 279 280 public void testForegroundTint() { 281 FrameLayout inflatedView = (FrameLayout) mActivity.findViewById(R.id.foreground_tint); 282 283 assertEquals("Foreground tint inflated correctly", 284 Color.WHITE, inflatedView.getForegroundTintList().getDefaultColor()); 285 assertEquals("Foreground tint mode inflated correctly", 286 PorterDuff.Mode.SRC_OVER, inflatedView.getForegroundTintMode()); 287 288 MockDrawable foreground = new MockDrawable(); 289 FrameLayout view = new FrameLayout(mActivity); 290 291 view.setForeground(foreground); 292 assertFalse("No foreground tint applied by default", foreground.hasCalledSetTint()); 293 294 view.setForegroundTintList(ColorStateList.valueOf(Color.WHITE)); 295 assertTrue("Foreground tint applied when setForegroundTintList() called after setForeground()", 296 foreground.hasCalledSetTint()); 297 298 foreground.reset(); 299 view.setForeground(null); 300 view.setForeground(foreground); 301 assertTrue("Foreground tint applied when setForegroundTintList() called before setForeground()", 302 foreground.hasCalledSetTint()); 303 } 304 305 private static void assertCenterAligned(View container, Drawable drawable) { 306 Rect rect = drawable.getBounds(); 307 int leftDelta = rect.left - container.getLeft(); 308 int rightDelta = container.getRight() - rect.right; 309 int topDelta = rect.top - container.getTop(); 310 int bottomDelta = container.getBottom() - rect.bottom; 311 312 assertTrue(Math.abs(leftDelta - rightDelta) <= 1); 313 assertTrue(Math.abs(topDelta - bottomDelta) <= 1); 314 } 315 316 private AttributeSet getAttributeSet() throws XmlPullParserException, IOException { 317 XmlPullParser parser = mActivity.getResources().getLayout(R.layout.framelayout_layout); 318 WidgetTestUtils.beginDocument(parser, "LinearLayout"); 319 return Xml.asAttributeSet(parser); 320 } 321 322 private static class MockDrawable extends Drawable { 323 private boolean mCalledSetTint = false; 324 325 @Override 326 public void draw(Canvas canvas) {} 327 328 @Override 329 public void setAlpha(int alpha) {} 330 331 @Override 332 public void setColorFilter(ColorFilter cf) {} 333 334 @Override 335 public void setTintList(ColorStateList tint) { 336 super.setTintList(tint); 337 mCalledSetTint = true; 338 } 339 340 @Override 341 public int getOpacity() { 342 return 0; 343 } 344 345 public boolean hasCalledSetTint() { 346 return mCalledSetTint; 347 } 348 349 public void reset() { 350 mCalledSetTint = false; 351 } 352 } 353 354 private static class MyFrameLayout extends FrameLayout { 355 public MyFrameLayout(Context context) { 356 super(context); 357 } 358 359 @Override 360 protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 361 return super.checkLayoutParams(p); 362 } 363 364 @Override 365 protected void drawableStateChanged() { 366 super.drawableStateChanged(); 367 } 368 369 @Override 370 protected LayoutParams generateDefaultLayoutParams() { 371 return super.generateDefaultLayoutParams(); 372 } 373 374 @Override 375 protected boolean verifyDrawable(Drawable who) { 376 return super.verifyDrawable(who); 377 } 378 379 @Override 380 protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 381 return super.generateLayoutParams(p); 382 } 383 } 384 } 385