• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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.view;
18 
19 import static androidx.test.InstrumentationRegistry.getContext;
20 
21 import static org.junit.Assert.assertEquals;
22 
23 import android.content.Context;
24 import android.graphics.Region;
25 import android.platform.test.annotations.Presubmit;
26 
27 import androidx.test.filters.SmallTest;
28 
29 import org.junit.Test;
30 
31 
32 /**
33  * Test basic functions of ViewGroup.
34  *
35  * Build/Install/Run:
36  *     atest FrameworksCoreTests:ViewGroupTest
37  */
38 @Presubmit
39 @SmallTest
40 public class ViewGroupTest {
41 
42     /**
43      * Test if {@link ViewGroup#subtractObscuredTouchableRegion} works as expected.
44      *
45      * The view hierarchy:
46      *   A---B---C
47      *    \   \
48      *     \   --D
49      *      \
50      *       E---F
51      *
52      * The layer and bounds of each view:
53      *   F -- (invisible)
54      *   E --
55      *   D ----
56      *   C ----------
57      *   B ------
58      *   A --------
59      */
60     @Test
testSubtractObscuredTouchableRegion()61     public void testSubtractObscuredTouchableRegion() {
62         final Context context = getContext();
63         final TestView viewA = new TestView(context, 8 /* right */);
64         final TestView viewB = new TestView(context, 6 /* right */);
65         final TestView viewC = new TestView(context, 10 /* right */);
66         final TestView viewD = new TestView(context, 4 /* right */);
67         final TestView viewE = new TestView(context, 2 /* right */);
68         final TestView viewF = new TestView(context, 2 /* right */);
69 
70         viewA.addView(viewB);
71         viewA.addView(viewE);
72         viewB.addView(viewC);
73         viewB.addView(viewD);
74         viewE.addView(viewF);
75 
76         viewF.setVisibility(View.INVISIBLE);
77 
78         final Region r = new Region();
79 
80         getUnobscuredTouchableRegion(r, viewA);
81         assertRegionContainPoint(1 /* x */, r, true /* contain */);
82         assertRegionContainPoint(3 /* x */, r, true /* contain */);
83         assertRegionContainPoint(5 /* x */, r, true /* contain */);
84         assertRegionContainPoint(7 /* x */, r, true /* contain */);
85         assertRegionContainPoint(9 /* x */, r, false /* contain */); // Outside of bounds
86 
87         getUnobscuredTouchableRegion(r, viewB);
88         assertRegionContainPoint(1 /* x */, r, false /* contain */); // Obscured by E
89         assertRegionContainPoint(3 /* x */, r, true /* contain */);
90         assertRegionContainPoint(5 /* x */, r, true /* contain */);
91         assertRegionContainPoint(7 /* x */, r, false /* contain */); // Outside of bounds
92 
93         getUnobscuredTouchableRegion(r, viewC);
94         assertRegionContainPoint(1 /* x */, r, false /* contain */); // Obscured by D and E
95         assertRegionContainPoint(3 /* x */, r, false /* contain */); // Obscured by D
96         assertRegionContainPoint(5 /* x */, r, true /* contain */);
97         assertRegionContainPoint(7 /* x */, r, false /* contain */); // Outside of parent bounds
98 
99         getUnobscuredTouchableRegion(r, viewD);
100         assertRegionContainPoint(1 /* x */, r, false /* contain */); // Obscured by E
101         assertRegionContainPoint(3 /* x */, r, true /* contain */);
102         assertRegionContainPoint(5 /* x */, r, false /* contain */); // Outside of bounds
103 
104         getUnobscuredTouchableRegion(r, viewE);
105         assertRegionContainPoint(1 /* x */, r, true /* contain */);
106         assertRegionContainPoint(3 /* x */, r, false /* contain */); // Outside of bounds
107     }
108 
getUnobscuredTouchableRegion(Region outRegion, View view)109     private static void getUnobscuredTouchableRegion(Region outRegion, View view) {
110         outRegion.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
111         final ViewParent parent = view.getParent();
112         if (parent != null) {
113             parent.subtractObscuredTouchableRegion(outRegion, view);
114         }
115     }
116 
assertRegionContainPoint(int x, Region region, boolean contain)117     private static void assertRegionContainPoint(int x, Region region, boolean contain) {
118         assertEquals(String.format("Touchable region must%s contain (%s, 0).",
119                 (contain ? "" : " not"), x), contain, region.contains(x, 0 /* y */));
120     }
121 
122     private static class TestView extends ViewGroup {
TestView(Context context, int right)123         TestView(Context context, int right) {
124             super(context);
125             setFrame(0 /* left */, 0 /* top */, right, 1 /* bottom */);
126         }
127 
128         @Override
onLayout(boolean changed, int l, int t, int r, int b)129         protected void onLayout(boolean changed, int l, int t, int r, int b) {
130             // We don't layout this view.
131         }
132     }
133 }
134