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