| /* |
| * Copyright 2018 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 androidx.appcompat.app; |
| |
| import static androidx.appcompat.testutils.DrawerLayoutActions.openDrawer; |
| import static androidx.test.espresso.Espresso.onView; |
| import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom; |
| |
| import static org.hamcrest.CoreMatchers.equalTo; |
| import static org.hamcrest.CoreMatchers.is; |
| import static org.hamcrest.MatcherAssert.assertThat; |
| |
| import android.app.Activity; |
| import android.content.Context; |
| import android.view.Gravity; |
| import android.view.InputDevice; |
| import android.view.MotionEvent; |
| import android.view.View; |
| import android.view.ViewGroup; |
| |
| import androidx.core.view.GravityCompat; |
| import androidx.drawerlayout.widget.DrawerLayout; |
| import androidx.test.core.app.ApplicationProvider; |
| import androidx.test.ext.junit.runners.AndroidJUnit4; |
| import androidx.test.filters.LargeTest; |
| import androidx.test.rule.ActivityTestRule; |
| |
| import org.junit.Before; |
| import org.junit.Rule; |
| import org.junit.Test; |
| import org.junit.runner.RunWith; |
| |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| |
| @RunWith(AndroidJUnit4.class) |
| public class DrawerInteractionTest { |
| |
| @Rule |
| public final ActivityTestRule<DrawerInteractionActivity> mActivityTestRule = |
| new ActivityTestRule<>(DrawerInteractionActivity.class); |
| |
| private TestDrawerLayout mDrawerLayout; |
| private MockView mStartDrawer; |
| private MockView mContentView; |
| |
| @Before |
| public void setUp() throws Throwable { |
| final Activity activity = mActivityTestRule.getActivity(); |
| |
| Context context = ApplicationProvider.getApplicationContext(); |
| mDrawerLayout = new TestDrawerLayout(ApplicationProvider.getApplicationContext()); |
| mContentView = new MockView(context); |
| mStartDrawer = new MockView(context); |
| |
| mDrawerLayout.setLayoutParams(new ViewGroup.LayoutParams(100, 100)); |
| DrawerLayout.LayoutParams contentViewLayoutParams = new DrawerLayout.LayoutParams(100, 100); |
| DrawerLayout.LayoutParams drawerViewLayoutParams = new DrawerLayout.LayoutParams(50, 100); |
| |
| contentViewLayoutParams.gravity = Gravity.NO_GRAVITY; |
| drawerViewLayoutParams.gravity = Gravity.START; |
| |
| mContentView.setLayoutParams(contentViewLayoutParams); |
| mStartDrawer.setLayoutParams(drawerViewLayoutParams); |
| mStartDrawer.setBackgroundColor(0xFF00FF00); |
| |
| mDrawerLayout.addView(mContentView); |
| mDrawerLayout.addView(mStartDrawer); |
| mDrawerLayout.setBackgroundColor(0xFFFF0000); |
| |
| mDrawerLayout.expectLayouts(1); |
| mActivityTestRule.runOnUiThread(new Runnable() { |
| @Override |
| public void run() { |
| activity.setContentView(mDrawerLayout); |
| } |
| }); |
| assertThat(mDrawerLayout.waitForLayouts(2), is(true)); |
| } |
| |
| // Verification that DrawerLayout blocks certain pointer motion events from getting to the |
| // content view when the drawer is open. |
| |
| @Test |
| @LargeTest |
| public void ui_pointerEvent_overDrawer_receivedByDrawer() throws Throwable { |
| onView(isAssignableFrom(DrawerLayout.class)).perform(openDrawer( |
| GravityCompat.START)); |
| MotionEvent motionEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_SCROLL, 25, 50, 0); |
| motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER); |
| |
| mDrawerLayout.dispatchGenericMotionEvent(motionEvent); |
| |
| assertThat(mStartDrawer.mMotionEventPassedToDispatchGenericMotionEvent, |
| is(equalTo(motionEvent))); |
| } |
| |
| @Test |
| @LargeTest |
| public void ui_pointerEvent_overDrawer_notReceivedByContent() throws Throwable { |
| onView(isAssignableFrom(DrawerLayout.class)).perform(openDrawer( |
| GravityCompat.START)); |
| MotionEvent motionEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_SCROLL, 25, 50, 0); |
| motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER); |
| |
| mDrawerLayout.dispatchGenericMotionEvent(motionEvent); |
| |
| assertThat(mContentView.mDispatchGenericMotionEventCalled, is(false)); |
| } |
| |
| @Test |
| @LargeTest |
| public void ui_pointerEvent_overContentDrawerOpen_notReceivedByContent() throws Throwable { |
| onView(isAssignableFrom(DrawerLayout.class)).perform(openDrawer( |
| GravityCompat.START)); |
| MotionEvent motionEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_SCROLL, 75, 50, 0); |
| motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER); |
| |
| mDrawerLayout.dispatchGenericMotionEvent(motionEvent); |
| |
| assertThat(mContentView.mDispatchGenericMotionEventCalled, is(false)); |
| } |
| |
| @Test |
| @LargeTest |
| public void ui_pointerEvent_overContentDrawerClosed_receivedByContent() { |
| MotionEvent motionEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_SCROLL, 75, 50, 0); |
| motionEvent.setSource(InputDevice.SOURCE_CLASS_POINTER); |
| |
| mDrawerLayout.dispatchGenericMotionEvent(motionEvent); |
| |
| assertThat(mContentView.mMotionEventPassedToDispatchGenericMotionEvent, |
| is(equalTo(motionEvent))); |
| } |
| |
| private class TestDrawerLayout extends DrawerLayout { |
| |
| CountDownLatch mLayoutCountDownLatch; |
| |
| TestDrawerLayout(Context context) { |
| super(context); |
| } |
| |
| public void expectLayouts(int count) { |
| mLayoutCountDownLatch = new CountDownLatch(count); |
| } |
| |
| public boolean waitForLayouts(int seconds) throws InterruptedException { |
| boolean result = mLayoutCountDownLatch.await(seconds, TimeUnit.SECONDS); |
| mLayoutCountDownLatch = null; |
| return result; |
| } |
| |
| @Override |
| protected void onLayout(boolean changed, int left, int top, int right, int bottom) { |
| super.onLayout(changed, left, top, right, bottom); |
| if (mLayoutCountDownLatch != null) { |
| mLayoutCountDownLatch.countDown(); |
| } |
| } |
| |
| } |
| |
| private class MockView extends View { |
| |
| MotionEvent mMotionEventPassedToDispatchGenericMotionEvent; |
| boolean mDispatchGenericMotionEventCalled = false; |
| |
| MockView(Context context) { |
| super(context); |
| } |
| |
| @Override |
| public boolean dispatchGenericMotionEvent(MotionEvent event) { |
| mMotionEventPassedToDispatchGenericMotionEvent = event; |
| mDispatchGenericMotionEventCalled = true; |
| return super.dispatchGenericMotionEvent(event); |
| } |
| } |
| |
| |
| } |