Home | History | Annotate | Download | only in cts
      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