| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.widget.cts; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertFalse; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| import static org.junit.Assert.assertSame; |
| import static org.junit.Assert.assertTrue; |
| import static org.mockito.Matchers.any; |
| import static org.mockito.Mockito.never; |
| import static org.mockito.Mockito.reset; |
| import static org.mockito.Mockito.spy; |
| import static org.mockito.Mockito.times; |
| import static org.mockito.Mockito.verify; |
| |
| import android.app.Activity; |
| import android.app.Instrumentation; |
| import android.content.Context; |
| import android.content.res.ColorStateList; |
| import android.graphics.Color; |
| import android.graphics.PorterDuff; |
| import android.graphics.Rect; |
| import android.graphics.Region; |
| import android.graphics.drawable.BitmapDrawable; |
| import android.graphics.drawable.ColorDrawable; |
| import android.graphics.drawable.Drawable; |
| import android.support.test.InstrumentationRegistry; |
| import android.support.test.annotation.UiThreadTest; |
| import android.support.test.filters.SmallTest; |
| import android.support.test.rule.ActivityTestRule; |
| import android.support.test.runner.AndroidJUnit4; |
| import android.util.AttributeSet; |
| import android.util.Xml; |
| import android.view.Gravity; |
| import android.view.View; |
| import android.view.ViewGroup; |
| import android.widget.Button; |
| import android.widget.FrameLayout; |
| import android.widget.FrameLayout.LayoutParams; |
| import android.widget.LinearLayout; |
| import android.widget.TextView; |
| |
| import com.android.compatibility.common.util.PollingCheck; |
| import com.android.compatibility.common.util.WidgetTestUtils; |
| |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| import org.mockito.ArgumentCaptor; |
| import org.xmlpull.v1.XmlPullParser; |
| import org.xmlpull.v1.XmlPullParserException; |
| |
| import java.io.IOException; |
| |
| @SmallTest |
| @RunWith(AndroidJUnit4.class) |
| public class FrameLayoutTest { |
| private Instrumentation mInstrumentation; |
| private Activity mActivity; |
| private FrameLayout mFrameLayout; |
| |
| @Rule |
| public ActivityTestRule<FrameLayoutCtsActivity> mActivityRule = |
| new ActivityTestRule<>(FrameLayoutCtsActivity.class); |
| |
| @Before |
| public void setup() { |
| mInstrumentation = InstrumentationRegistry.getInstrumentation(); |
| mActivity = mActivityRule.getActivity(); |
| mFrameLayout = (FrameLayout) mActivity.findViewById(R.id.framelayout); |
| } |
| |
| @Test |
| public void testConstructor() throws XmlPullParserException, IOException { |
| AttributeSet attrs = getAttributeSet(); |
| |
| new FrameLayout(mActivity); |
| new FrameLayout(mActivity, attrs); |
| new FrameLayout(mActivity, attrs, 0); |
| } |
| |
| @Test |
| public void testSetForegroundGravity() throws Throwable { |
| final BitmapDrawable foreground |
| = (BitmapDrawable) mActivity.getResources().getDrawable(R.drawable.size_48x48); |
| WidgetTestUtils.assertScaledPixels(48, foreground.getIntrinsicHeight(), mActivity); |
| WidgetTestUtils.assertScaledPixels(48, foreground.getIntrinsicWidth(), mActivity); |
| assertTrue(mFrameLayout.getHeight() > foreground.getIntrinsicHeight()); |
| assertTrue(mFrameLayout.getWidth() > foreground.getIntrinsicWidth()); |
| assertNull(mFrameLayout.getForeground()); |
| |
| WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mFrameLayout, |
| () -> mFrameLayout.setForeground(foreground)); |
| assertSame(foreground, mFrameLayout.getForeground()); |
| // check the default gravity FILL, it completely fills its container |
| assertTrue(foreground.isVisible()); |
| final Rect rect = foreground.getBounds(); |
| // foreground has been stretched |
| PollingCheck.waitFor(() -> mFrameLayout.getHeight() == rect.bottom - rect.top); |
| assertEquals(mFrameLayout.getWidth(), rect.right - rect.left); |
| |
| // should get a new foreground again, because former foreground has been stretched |
| final BitmapDrawable newForeground = |
| (BitmapDrawable) mActivity.getDrawable(R.drawable.size_48x48); |
| WidgetTestUtils.assertScaledPixels(48, newForeground.getIntrinsicHeight(), mActivity); |
| WidgetTestUtils.assertScaledPixels(48, newForeground.getIntrinsicWidth(), mActivity); |
| assertTrue(mFrameLayout.getHeight() > newForeground.getIntrinsicHeight()); |
| assertTrue(mFrameLayout.getWidth() > foreground.getIntrinsicWidth()); |
| |
| WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mFrameLayout, () -> { |
| mFrameLayout.setForeground(newForeground); |
| mFrameLayout.setForegroundGravity(Gravity.CENTER); |
| }); |
| mInstrumentation.waitForIdleSync(); |
| assertSame(newForeground, mFrameLayout.getForeground()); |
| assertTrue(newForeground.isVisible()); |
| Rect rect2 = newForeground.getBounds(); |
| // not changing its size |
| assertEquals(foreground.getIntrinsicHeight(), rect2.bottom - rect2.top); |
| assertEquals(foreground.getIntrinsicWidth(), rect2.right - rect2.left); |
| assertCenterAligned(mFrameLayout, newForeground); |
| } |
| |
| @Test |
| public void testGatherTransparentRegion() throws Throwable { |
| final LinearLayout container = |
| (LinearLayout) mActivity.findViewById(R.id.framelayout_container); |
| final Drawable foreground = mActivity.getResources().getDrawable(R.drawable.size_48x48); |
| WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mFrameLayout, () -> { |
| mFrameLayout.setForeground(foreground); |
| mFrameLayout.setForegroundGravity(Gravity.CENTER); |
| }); |
| mInstrumentation.waitForIdleSync(); |
| Region region = new Region(foreground.getBounds()); |
| assertTrue(mFrameLayout.gatherTransparentRegion(region)); |
| |
| WidgetTestUtils.runOnMainAndDrawSync(mActivityRule, mFrameLayout, |
| () -> container.requestTransparentRegion(mFrameLayout)); |
| mInstrumentation.waitForIdleSync(); |
| region = new Region(foreground.getBounds()); |
| assertTrue(mFrameLayout.gatherTransparentRegion(region)); |
| } |
| |
| @Test |
| public void testAccessMeasureAllChildren() throws Throwable { |
| final FrameLayout frameLayout |
| = (FrameLayout) mActivity.findViewById(R.id.framelayout_measureall); |
| assertFalse(frameLayout.getConsiderGoneChildrenWhenMeasuring()); |
| |
| // text view and button are VISIBLE, they should be measured |
| final TextView textView = (TextView) frameLayout.findViewById(R.id.framelayout_textview); |
| WidgetTestUtils.assertScaledPixels(30, textView.getMeasuredHeight(), mActivity); |
| WidgetTestUtils.assertScaledPixels(60, textView.getMeasuredWidth(), mActivity); |
| assertEquals(textView.getMeasuredHeight(), frameLayout.getMeasuredHeight()); |
| assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth()); |
| |
| // measureAll is false and text view is GONE, text view will NOT be measured |
| mActivityRule.runOnUiThread(() -> { |
| textView.setVisibility(View.GONE); |
| frameLayout.requestLayout(); |
| }); |
| mInstrumentation.waitForIdleSync(); |
| assertFalse(frameLayout.getConsiderGoneChildrenWhenMeasuring()); |
| Button button = (Button) frameLayout.findViewById(R.id.framelayout_button); |
| WidgetTestUtils.assertScaledPixels(15, button.getMeasuredHeight(), mActivity); |
| WidgetTestUtils.assertScaledPixels(50, button.getMeasuredWidth(), mActivity); |
| assertEquals(button.getMeasuredHeight(), frameLayout.getMeasuredHeight()); |
| assertEquals(button.getMeasuredWidth(), frameLayout.getMeasuredWidth()); |
| |
| // measureAll is true and text view is GONE, text view will be measured |
| mActivityRule.runOnUiThread(() -> { |
| frameLayout.setMeasureAllChildren(true); |
| frameLayout.requestLayout(); |
| }); |
| mInstrumentation.waitForIdleSync(); |
| assertTrue(frameLayout.getMeasureAllChildren()); |
| assertTrue(frameLayout.getConsiderGoneChildrenWhenMeasuring()); |
| assertEquals(textView.getMeasuredHeight(), frameLayout.getMeasuredHeight()); |
| assertEquals(textView.getMeasuredWidth(), frameLayout.getMeasuredWidth()); |
| } |
| |
| @Test |
| public void testGenerateLayoutParams1() { |
| MyFrameLayout myFrameLayout = new MyFrameLayout(mActivity); |
| ViewGroup.LayoutParams p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, |
| ViewGroup.LayoutParams.WRAP_CONTENT); |
| |
| ViewGroup.LayoutParams params = myFrameLayout.generateLayoutParams(p); |
| assertNotNull(params); |
| assertTrue(params instanceof FrameLayout.LayoutParams); |
| assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, params.width); |
| assertEquals(ViewGroup.LayoutParams.WRAP_CONTENT, params.height); |
| } |
| |
| @Test |
| public void testGenerateLayoutParams2() throws XmlPullParserException, IOException { |
| AttributeSet attrs = getAttributeSet(); |
| |
| FrameLayout.LayoutParams params = mFrameLayout.generateLayoutParams(attrs); |
| assertNotNull(params); |
| assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, params.width); |
| assertEquals(ViewGroup.LayoutParams.MATCH_PARENT, params.height); |
| assertEquals(Gravity.BOTTOM, params.gravity); |
| } |
| |
| @Test |
| public void testCheckLayoutParams() { |
| MyFrameLayout myFrameLayout = new MyFrameLayout(mActivity); |
| assertFalse(myFrameLayout.checkLayoutParams(null)); |
| |
| int width = 120; |
| int height = 80; |
| ViewGroup.LayoutParams params1 = new ViewGroup.LayoutParams(width, height); |
| assertFalse(myFrameLayout.checkLayoutParams(params1)); |
| |
| FrameLayout.LayoutParams params2 = new FrameLayout.LayoutParams(width, height); |
| assertTrue(myFrameLayout.checkLayoutParams(params2)); |
| } |
| |
| @Test |
| public void testGenerateLayoutParamsFromMarginParams() { |
| MyFrameLayout myFrameLayout = new MyFrameLayout(mActivity); |
| ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams(3, 5); |
| lp.leftMargin = 1; |
| lp.topMargin = 2; |
| lp.rightMargin = 3; |
| lp.bottomMargin = 4; |
| LayoutParams generated = (LayoutParams) myFrameLayout.generateLayoutParams(lp); |
| assertNotNull(generated); |
| assertEquals(3, generated.width); |
| assertEquals(5, generated.height); |
| |
| assertEquals(1, generated.leftMargin); |
| assertEquals(2, generated.topMargin); |
| assertEquals(3, generated.rightMargin); |
| assertEquals(4, generated.bottomMargin); |
| } |
| |
| @Test |
| public void testGenerateDefaultLayoutParams() { |
| MyFrameLayout frameLayout = new MyFrameLayout(mActivity); |
| FrameLayout.LayoutParams params = frameLayout.generateDefaultLayoutParams(); |
| |
| assertNotNull(params); |
| assertEquals(LayoutParams.MATCH_PARENT, params.width); |
| assertEquals(LayoutParams.MATCH_PARENT, params.height); |
| } |
| |
| @Test |
| public void testVerifyDrawable() { |
| MyFrameLayout myFrameLayout = new MyFrameLayout(mActivity); |
| |
| Drawable drawable = mActivity.getResources().getDrawable(R.drawable.scenery); |
| myFrameLayout.setForeground(drawable); |
| assertTrue(myFrameLayout.verifyDrawable(drawable)); |
| |
| drawable = mActivity.getResources().getDrawable(R.drawable.black); |
| assertFalse(myFrameLayout.verifyDrawable(drawable)); |
| |
| assertTrue(myFrameLayout.verifyDrawable(null)); |
| } |
| |
| @UiThreadTest |
| @Test |
| public void testForegroundTint() { |
| FrameLayout inflatedView = (FrameLayout) mActivity.findViewById(R.id.foreground_tint); |
| |
| assertEquals("Foreground tint inflated correctly", |
| Color.WHITE, inflatedView.getForegroundTintList().getDefaultColor()); |
| assertEquals("Foreground tint mode inflated correctly", |
| PorterDuff.Mode.SRC_OVER, inflatedView.getForegroundTintMode()); |
| |
| final Drawable foreground = spy(new ColorDrawable()); |
| FrameLayout view = new FrameLayout(mActivity); |
| |
| view.setForeground(foreground); |
| verify(foreground, never()).setTintList(any(ColorStateList.class)); |
| |
| view.setForegroundTintList(ColorStateList.valueOf(Color.RED)); |
| final ArgumentCaptor<ColorStateList> colorStateListCaptor = |
| ArgumentCaptor.forClass(ColorStateList.class); |
| verify(foreground, times(1)).setTintList(colorStateListCaptor.capture()); |
| assertEquals(1, colorStateListCaptor.getValue().getColors().length); |
| assertEquals(Color.RED, colorStateListCaptor.getValue().getColors()[0]); |
| |
| reset(foreground); |
| view.setForeground(null); |
| view.setForeground(foreground); |
| verify(foreground, times(1)).setTintList(colorStateListCaptor.capture()); |
| assertEquals(1, colorStateListCaptor.getValue().getColors().length); |
| assertEquals(Color.RED, colorStateListCaptor.getValue().getColors()[0]); |
| } |
| |
| private static void assertCenterAligned(View container, Drawable drawable) { |
| Rect rect = drawable.getBounds(); |
| int leftDelta = rect.left - container.getLeft(); |
| int rightDelta = container.getRight() - rect.right; |
| int topDelta = rect.top - container.getTop(); |
| int bottomDelta = container.getBottom() - rect.bottom; |
| |
| assertTrue(Math.abs(leftDelta - rightDelta) <= 1); |
| assertTrue(Math.abs(topDelta - bottomDelta) <= 1); |
| } |
| |
| private AttributeSet getAttributeSet() throws XmlPullParserException, IOException { |
| XmlPullParser parser = mActivity.getResources().getLayout(R.layout.framelayout_layout); |
| WidgetTestUtils.beginDocument(parser, "LinearLayout"); |
| return Xml.asAttributeSet(parser); |
| } |
| |
| private static class MyFrameLayout extends FrameLayout { |
| public MyFrameLayout(Context context) { |
| super(context); |
| } |
| |
| @Override |
| protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { |
| return super.checkLayoutParams(p); |
| } |
| |
| @Override |
| protected void drawableStateChanged() { |
| super.drawableStateChanged(); |
| } |
| |
| @Override |
| protected LayoutParams generateDefaultLayoutParams() { |
| return super.generateDefaultLayoutParams(); |
| } |
| |
| @Override |
| protected boolean verifyDrawable(Drawable who) { |
| return super.verifyDrawable(who); |
| } |
| |
| @Override |
| protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { |
| return super.generateLayoutParams(p); |
| } |
| } |
| } |