Merge "Detects nav bar gestures to progress through Home tutorial." into ub-launcher3-rvc-dev
diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
index d58ab5d..ff98701 100644
--- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java
@@ -22,6 +22,7 @@
import com.android.launcher3.R;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
+import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
/** A {@link TutorialController} for the Back tutorial. */
final class BackGestureTutorialController extends TutorialController {
@@ -114,4 +115,13 @@
break;
}
}
+
+ @Override
+ public void onNavBarGestureAttempted(NavBarGestureResult result) {
+ if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
+ if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) {
+ mTutorialFragment.closeTutorial();
+ }
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
index 0bf996d..95b3c79 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -21,6 +21,7 @@
import com.android.launcher3.R;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
+import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
/** A {@link TutorialController} for the Home tutorial. */
final class HomeGestureTutorialController extends TutorialController {
@@ -82,4 +83,21 @@
break;
}
}
+
+ @Override
+ public void onNavBarGestureAttempted(NavBarGestureResult result) {
+ switch (mTutorialType) {
+ case HOME_NAVIGATION:
+ if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) {
+ hideHandCoachingAnimation();
+ mTutorialFragment.changeController(HOME_NAVIGATION_COMPLETE);
+ }
+ break;
+ case HOME_NAVIGATION_COMPLETE:
+ if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) {
+ mTutorialFragment.closeTutorial();
+ }
+ break;
+ }
+ }
}
diff --git a/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
new file mode 100644
index 0000000..6d8caa2
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/interaction/NavBarGestureHandler.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2020 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 com.android.quickstep.interaction;
+
+import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.HOME_GESTURE_COMPLETED;
+import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.HOME_NOT_STARTED_TOO_FAR_FROM_EDGE;
+import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION;
+import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.OVERVIEW_GESTURE_COMPLETED;
+import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.view.Display;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.View;
+import android.view.View.OnTouchListener;
+
+import com.android.launcher3.ResourceUtils;
+import com.android.quickstep.SysUINavigationMode.Mode;
+import com.android.quickstep.util.NavBarPosition;
+import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
+
+/** Utility class to handle home gestures. */
+public class NavBarGestureHandler implements OnTouchListener {
+
+ private static final String LOG_TAG = "NavBarGestureHandler";
+
+ private final Point mDisplaySize = new Point();
+ private final TriggerSwipeUpTouchTracker mSwipeUpTouchTracker;
+ private int mBottomGestureHeight;
+ private boolean mTouchCameFromNavBar;
+ private NavBarGestureAttemptCallback mGestureCallback;
+
+ NavBarGestureHandler(Context context) {
+ final Display display = context.getDisplay();
+ final int displayRotation;
+ if (display == null) {
+ displayRotation = Surface.ROTATION_0;
+ } else {
+ displayRotation = display.getRotation();
+ display.getRealSize(mDisplaySize);
+ }
+ mSwipeUpTouchTracker =
+ new TriggerSwipeUpTouchTracker(context, true /*disableHorizontalSwipe*/,
+ new NavBarPosition(Mode.NO_BUTTON, displayRotation),
+ null /*onInterceptTouch*/, this::onSwipeUp);
+
+ final Resources resources = context.getResources();
+ mBottomGestureHeight =
+ ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, resources);
+ }
+
+ void registerNavBarGestureAttemptCallback(NavBarGestureAttemptCallback callback) {
+ mGestureCallback = callback;
+ }
+
+ void unregisterNavBarGestureAttemptCallback() {
+ mGestureCallback = null;
+ }
+
+ private void onSwipeUp(boolean wasFling) {
+ if (mGestureCallback == null) {
+ return;
+ }
+ if (mTouchCameFromNavBar) {
+ mGestureCallback.onNavBarGestureAttempted(wasFling
+ ? HOME_GESTURE_COMPLETED : OVERVIEW_GESTURE_COMPLETED);
+ } else {
+ mGestureCallback.onNavBarGestureAttempted(wasFling
+ ? HOME_NOT_STARTED_TOO_FAR_FROM_EDGE : OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE);
+ }
+ }
+
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ int action = motionEvent.getAction();
+ boolean intercepted = mSwipeUpTouchTracker.interceptedTouch();
+ if (action == MotionEvent.ACTION_DOWN) {
+ mTouchCameFromNavBar = motionEvent.getRawY() >= mDisplaySize.y - mBottomGestureHeight;
+ mSwipeUpTouchTracker.init();
+ } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
+ if (mGestureCallback != null && !intercepted && mTouchCameFromNavBar) {
+ mGestureCallback.onNavBarGestureAttempted(
+ HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION);
+ intercepted = true;
+ }
+ }
+ mSwipeUpTouchTracker.onMotionEvent(motionEvent);
+ return intercepted;
+ }
+
+ enum NavBarGestureResult {
+ UNKNOWN,
+ HOME_GESTURE_COMPLETED,
+ OVERVIEW_GESTURE_COMPLETED,
+ HOME_NOT_STARTED_TOO_FAR_FROM_EDGE,
+ OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE,
+ HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION // Side swipe on nav bar.
+ }
+
+ /** Callback to let the UI react to attempted nav bar gestures. */
+ interface NavBarGestureAttemptCallback {
+ /** Called whenever any touch is completed. */
+ void onNavBarGestureAttempted(NavBarGestureResult result);
+ }
+}
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
index f0cb567..69c61ce 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -26,9 +26,11 @@
import androidx.annotation.Nullable;
import com.android.launcher3.R;
-import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
+import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
+import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureAttemptCallback;
-abstract class TutorialController {
+abstract class TutorialController implements BackGestureAttemptCallback,
+ NavBarGestureAttemptCallback {
final TutorialFragment mTutorialFragment;
final TutorialType mTutorialType;
@@ -58,8 +60,6 @@
mActionButton = rootView.findViewById(R.id.gesture_tutorial_fragment_action_button);
}
- abstract void onBackGestureAttempted(BackGestureResult result);
-
@Nullable
Integer getTitleStringId() {
return null;
@@ -86,6 +86,7 @@
void hideHandCoachingAnimation() {
mHandCoachingAnimation.stop();
+ mHandCoachingView.setVisibility(View.INVISIBLE);
}
@CallSuper
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
index 6346a9b..3d02525 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java
@@ -21,7 +21,9 @@
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
+import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.WindowInsets;
@@ -31,13 +33,11 @@
import androidx.fragment.app.FragmentActivity;
import com.android.launcher3.R;
-import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
-import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
import com.android.quickstep.interaction.TutorialController.TutorialType;
import java.net.URISyntaxException;
-abstract class TutorialFragment extends Fragment implements BackGestureAttemptCallback {
+abstract class TutorialFragment extends Fragment implements OnTouchListener {
private static final String LOG_TAG = "TutorialFragment";
private static final String SYSTEM_NAVIGATION_SETTING_INTENT =
@@ -52,6 +52,7 @@
View mRootView;
TutorialHandAnimation mHandCoachingAnimation;
EdgeBackGestureHandler mEdgeBackGestureHandler;
+ NavBarGestureHandler mNavBarGestureHandler;
public static TutorialFragment newInstance(TutorialType tutorialType) {
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
@@ -91,13 +92,14 @@
Bundle args = savedInstanceState != null ? savedInstanceState : getArguments();
mTutorialType = (TutorialType) args.getSerializable(KEY_TUTORIAL_TYPE);
mEdgeBackGestureHandler = new EdgeBackGestureHandler(getContext());
- mEdgeBackGestureHandler.registerBackGestureAttemptCallback(this);
+ mNavBarGestureHandler = new NavBarGestureHandler(getContext());
}
@Override
public void onDestroy() {
super.onDestroy();
mEdgeBackGestureHandler.unregisterBackGestureAttemptCallback();
+ mNavBarGestureHandler.unregisterNavBarGestureAttemptCallback();
}
@Override
@@ -111,7 +113,7 @@
mEdgeBackGestureHandler.setInsets(systemInsets.left, systemInsets.right);
return insets;
});
- mRootView.setOnTouchListener(mEdgeBackGestureHandler);
+ mRootView.setOnTouchListener(this);
mHandCoachingAnimation = new TutorialHandAnimation(getContext(), mRootView,
getHandAnimationResId());
return mRootView;
@@ -129,6 +131,13 @@
mHandCoachingAnimation.stop();
}
+ @Override
+ public boolean onTouch(View view, MotionEvent motionEvent) {
+ // Note: Using logical or to ensure both functions get called.
+ return mEdgeBackGestureHandler.onTouch(view, motionEvent)
+ | mNavBarGestureHandler.onTouch(view, motionEvent);
+ }
+
void onAttachedToWindow() {
mEdgeBackGestureHandler.setViewGroupParent((ViewGroup) getRootView());
}
@@ -140,6 +149,8 @@
void changeController(TutorialType tutorialType) {
mTutorialController = createController(tutorialType);
mTutorialController.transitToController();
+ mEdgeBackGestureHandler.registerBackGestureAttemptCallback(mTutorialController);
+ mNavBarGestureHandler.registerNavBarGestureAttemptCallback(mTutorialController);
mTutorialType = tutorialType;
}
@@ -157,13 +168,6 @@
return mHandCoachingAnimation;
}
- @Override
- public void onBackGestureAttempted(BackGestureResult result) {
- if (mTutorialController != null) {
- mTutorialController.onBackGestureAttempted(result);
- }
- }
-
void closeTutorial() {
FragmentActivity activity = getActivity();
if (activity != null) {
diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialHandAnimation.java b/quickstep/src/com/android/quickstep/interaction/TutorialHandAnimation.java
index 5362aaf..c810e43 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialHandAnimation.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialHandAnimation.java
@@ -45,6 +45,7 @@
/** [Re]starts animation for the given tutorial. */
void startLoopedAnimation(TutorialType tutorialType) {
+ mHandCoachingView.setVisibility(View.VISIBLE);
if (mGestureAnimation.isRunning()) {
stop();
}
diff --git a/quickstep/src/com/android/quickstep/util/NavBarPosition.java b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
index 74e6b29..0a98e1b 100644
--- a/quickstep/src/com/android/quickstep/util/NavBarPosition.java
+++ b/quickstep/src/com/android/quickstep/util/NavBarPosition.java
@@ -35,6 +35,11 @@
mDisplayRotation = info.rotation;
}
+ public NavBarPosition(SysUINavigationMode.Mode mode, int displayRotation) {
+ mMode = mode;
+ mDisplayRotation = displayRotation;
+ }
+
public boolean isRightEdge() {
return mMode != NO_BUTTON && mDisplayRotation == Surface.ROTATION_90;
}