CoordinatorLayoutTest.java revision 6206ad57276146c8f70e939fd40ce9c7b88767f6
1/* 2 * Copyright (C) 2016 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 17package android.support.design.widget; 18 19import static org.hamcrest.CoreMatchers.is; 20import static org.hamcrest.MatcherAssert.assertThat; 21import static org.junit.Assert.assertFalse; 22import static org.mockito.Matchers.any; 23import static org.mockito.Matchers.same; 24import static org.mockito.Mockito.atLeastOnce; 25import static org.mockito.Mockito.doCallRealMethod; 26import static org.mockito.Mockito.mock; 27import static org.mockito.Mockito.never; 28import static org.mockito.Mockito.verify; 29 30import android.app.Instrumentation; 31import android.support.test.InstrumentationRegistry; 32import android.support.test.filters.SdkSuppress; 33import android.support.v4.view.ViewCompat; 34import android.support.v4.view.WindowInsetsCompat; 35import android.test.suitebuilder.annotation.MediumTest; 36import android.view.Gravity; 37import android.view.View; 38 39import org.junit.Test; 40 41import java.util.List; 42import java.util.concurrent.atomic.AtomicInteger; 43 44@MediumTest 45public class CoordinatorLayoutTest extends BaseInstrumentationTestCase<CoordinatorLayoutActivity> { 46 47 public CoordinatorLayoutTest() { 48 super(CoordinatorLayoutActivity.class); 49 } 50 51 @Test 52 @SdkSuppress(minSdkVersion = 21) 53 public void testSetFitSystemWindows() { 54 final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 55 final CoordinatorLayout col = mActivityTestRule.getActivity().mCoordinatorLayout; 56 final View view = new View(col.getContext()); 57 58 // Create a mock which calls the default impl of onApplyWindowInsets() 59 final CoordinatorLayout.Behavior<View> mockBehavior = 60 mock(CoordinatorLayout.Behavior.class); 61 doCallRealMethod().when(mockBehavior) 62 .onApplyWindowInsets(same(col), same(view), any(WindowInsetsCompat.class)); 63 64 // Assert that the CoL is currently not set to fitSystemWindows 65 assertFalse(col.getFitsSystemWindows()); 66 67 // Now add a view with our mocked behavior to the CoordinatorLayout 68 view.setFitsSystemWindows(true); 69 instrumentation.runOnMainSync(new Runnable() { 70 @Override 71 public void run() { 72 final CoordinatorLayout.LayoutParams lp = col.generateDefaultLayoutParams(); 73 lp.setBehavior(mockBehavior); 74 col.addView(view, lp); 75 } 76 }); 77 instrumentation.waitForIdleSync(); 78 79 // Now request some insets and wait for the pass to happen 80 instrumentation.runOnMainSync(new Runnable() { 81 @Override 82 public void run() { 83 col.requestApplyInsets(); 84 } 85 }); 86 instrumentation.waitForIdleSync(); 87 88 // Verify that onApplyWindowInsets() has not been called 89 verify(mockBehavior, never()) 90 .onApplyWindowInsets(same(col), same(view), any(WindowInsetsCompat.class)); 91 92 // Now enable fits system windows and wait for a pass to happen 93 instrumentation.runOnMainSync(new Runnable() { 94 @Override 95 public void run() { 96 col.setFitsSystemWindows(true); 97 } 98 }); 99 instrumentation.waitForIdleSync(); 100 101 // Verify that onApplyWindowInsets() has been called with some insets 102 verify(mockBehavior, atLeastOnce()) 103 .onApplyWindowInsets(same(col), same(view), any(WindowInsetsCompat.class)); 104 } 105 106 @Test 107 public void testInsetDependency() { 108 final CoordinatorLayout col = mActivityTestRule.getActivity().mCoordinatorLayout; 109 110 final CoordinatorLayout.LayoutParams lpInsetLeft = col.generateDefaultLayoutParams(); 111 lpInsetLeft.insetEdge = Gravity.LEFT; 112 113 final CoordinatorLayout.LayoutParams lpInsetRight = col.generateDefaultLayoutParams(); 114 lpInsetRight.insetEdge = Gravity.RIGHT; 115 116 final CoordinatorLayout.LayoutParams lpInsetTop = col.generateDefaultLayoutParams(); 117 lpInsetTop.insetEdge = Gravity.TOP; 118 119 final CoordinatorLayout.LayoutParams lpInsetBottom = col.generateDefaultLayoutParams(); 120 lpInsetBottom.insetEdge = Gravity.BOTTOM; 121 122 final CoordinatorLayout.LayoutParams lpDodgeLeft = col.generateDefaultLayoutParams(); 123 lpDodgeLeft.dodgeInsetEdges = Gravity.LEFT; 124 125 final CoordinatorLayout.LayoutParams lpDodgeLeftAndTop = col.generateDefaultLayoutParams(); 126 lpDodgeLeftAndTop.dodgeInsetEdges = Gravity.LEFT | Gravity.TOP; 127 128 final CoordinatorLayout.LayoutParams lpDodgeAll = col.generateDefaultLayoutParams(); 129 lpDodgeAll.dodgeInsetEdges = Gravity.FILL; 130 131 final View a = new View(col.getContext()); 132 final View b = new View(col.getContext()); 133 134 assertThat(dependsOn(lpDodgeLeft, lpInsetLeft, col, a, b), is(true)); 135 assertThat(dependsOn(lpDodgeLeft, lpInsetRight, col, a, b), is(false)); 136 assertThat(dependsOn(lpDodgeLeft, lpInsetTop, col, a, b), is(false)); 137 assertThat(dependsOn(lpDodgeLeft, lpInsetBottom, col, a, b), is(false)); 138 139 assertThat(dependsOn(lpDodgeLeftAndTop, lpInsetLeft, col, a, b), is(true)); 140 assertThat(dependsOn(lpDodgeLeftAndTop, lpInsetRight, col, a, b), is(false)); 141 assertThat(dependsOn(lpDodgeLeftAndTop, lpInsetTop, col, a, b), is(true)); 142 assertThat(dependsOn(lpDodgeLeftAndTop, lpInsetBottom, col, a, b), is(false)); 143 144 assertThat(dependsOn(lpDodgeAll, lpInsetLeft, col, a, b), is(true)); 145 assertThat(dependsOn(lpDodgeAll, lpInsetRight, col, a, b), is(true)); 146 assertThat(dependsOn(lpDodgeAll, lpInsetTop, col, a, b), is(true)); 147 assertThat(dependsOn(lpDodgeAll, lpInsetBottom, col, a, b), is(true)); 148 149 assertThat(dependsOn(lpInsetLeft, lpDodgeLeft, col, a, b), is(false)); 150 } 151 152 private static boolean dependsOn(CoordinatorLayout.LayoutParams lpChild, 153 CoordinatorLayout.LayoutParams lpDependency, CoordinatorLayout col, 154 View child, View dependency) { 155 child.setLayoutParams(lpChild); 156 dependency.setLayoutParams(lpDependency); 157 return lpChild.dependsOn(col, child, dependency); 158 } 159 160 @Test 161 public void testInsetEdge() { 162 final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 163 final CoordinatorLayout col = mActivityTestRule.getActivity().mCoordinatorLayout; 164 165 final View insetView = new View(col.getContext()); 166 final View dodgeInsetView = new View(col.getContext()); 167 final AtomicInteger originalTop = new AtomicInteger(); 168 169 instrumentation.runOnMainSync(new Runnable() { 170 @Override 171 public void run() { 172 CoordinatorLayout.LayoutParams lpInsetView = col.generateDefaultLayoutParams(); 173 lpInsetView.width = CoordinatorLayout.LayoutParams.MATCH_PARENT; 174 lpInsetView.height = 100; 175 lpInsetView.gravity = Gravity.TOP | Gravity.LEFT; 176 lpInsetView.insetEdge = Gravity.TOP; 177 col.addView(insetView, lpInsetView); 178 insetView.setBackgroundColor(0xFF0000FF); 179 180 CoordinatorLayout.LayoutParams lpDodgeInsetView = col.generateDefaultLayoutParams(); 181 lpDodgeInsetView.width = 100; 182 lpDodgeInsetView.height = 100; 183 lpDodgeInsetView.gravity = Gravity.TOP | Gravity.LEFT; 184 lpDodgeInsetView.dodgeInsetEdges = Gravity.TOP; 185 col.addView(dodgeInsetView, lpDodgeInsetView); 186 dodgeInsetView.setBackgroundColor(0xFFFF0000); 187 } 188 }); 189 instrumentation.waitForIdleSync(); 190 instrumentation.runOnMainSync(new Runnable() { 191 @Override 192 public void run() { 193 List<View> dependencies = col.getDependencies(dodgeInsetView); 194 assertThat(dependencies.size(), is(1)); 195 assertThat(dependencies.get(0), is(insetView)); 196 197 // Move the insetting view 198 originalTop.set(dodgeInsetView.getTop()); 199 assertThat(originalTop.get(), is(insetView.getBottom())); 200 ViewCompat.offsetTopAndBottom(insetView, 123); 201 } 202 }); 203 instrumentation.waitForIdleSync(); 204 instrumentation.runOnMainSync(new Runnable() { 205 @Override 206 public void run() { 207 // Confirm that the dodging view was moved by the same size 208 assertThat(dodgeInsetView.getTop() - originalTop.get(), is(123)); 209 } 210 }); 211 } 212 213} 214