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