Merge "Detects nav bar gestures to progress through Home tutorial." into ub-launcher3-rvc-dev

This commit is contained in:
TreeHugger Robot 2020-04-24 18:58:30 +00:00 committed by Android (Google) Code Review
commit acafb3a287
7 changed files with 176 additions and 16 deletions

View File

@ -22,6 +22,7 @@ import android.view.View;
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 @@ final class BackGestureTutorialController extends TutorialController {
break;
}
}
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result) {
if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) {
mTutorialFragment.closeTutorial();
}
}
}
}

View File

@ -21,6 +21,7 @@ import android.view.View;
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 @@ final class HomeGestureTutorialController extends TutorialController {
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;
}
}
}

View File

@ -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);
}
}

View File

@ -26,9 +26,11 @@ import androidx.annotation.CallSuper;
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 @@ abstract class TutorialController {
mActionButton = rootView.findViewById(R.id.gesture_tutorial_fragment_action_button);
}
abstract void onBackGestureAttempted(BackGestureResult result);
@Nullable
Integer getTitleStringId() {
return null;
@ -86,6 +86,7 @@ abstract class TutorialController {
void hideHandCoachingAnimation() {
mHandCoachingAnimation.stop();
mHandCoachingView.setVisibility(View.INVISIBLE);
}
@CallSuper

View File

@ -21,7 +21,9 @@ import android.graphics.Insets;
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.Fragment;
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 @@ abstract class TutorialFragment extends Fragment implements BackGestureAttemptCa
View mRootView;
TutorialHandAnimation mHandCoachingAnimation;
EdgeBackGestureHandler mEdgeBackGestureHandler;
NavBarGestureHandler mNavBarGestureHandler;
public static TutorialFragment newInstance(TutorialType tutorialType) {
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
@ -91,13 +92,14 @@ abstract class TutorialFragment extends Fragment implements BackGestureAttemptCa
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 @@ abstract class TutorialFragment extends Fragment implements BackGestureAttemptCa
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 @@ abstract class TutorialFragment extends Fragment implements BackGestureAttemptCa
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 @@ abstract class TutorialFragment extends Fragment implements BackGestureAttemptCa
void changeController(TutorialType tutorialType) {
mTutorialController = createController(tutorialType);
mTutorialController.transitToController();
mEdgeBackGestureHandler.registerBackGestureAttemptCallback(mTutorialController);
mNavBarGestureHandler.registerNavBarGestureAttemptCallback(mTutorialController);
mTutorialType = tutorialType;
}
@ -157,13 +168,6 @@ abstract class TutorialFragment extends Fragment implements BackGestureAttemptCa
return mHandCoachingAnimation;
}
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (mTutorialController != null) {
mTutorialController.onBackGestureAttempted(result);
}
}
void closeTutorial() {
FragmentActivity activity = getActivity();
if (activity != null) {

View File

@ -45,6 +45,7 @@ final class TutorialHandAnimation {
/** [Re]starts animation for the given tutorial. */
void startLoopedAnimation(TutorialType tutorialType) {
mHandCoachingView.setVisibility(View.VISIBLE);
if (mGestureAnimation.isRunning()) {
stop();
}

View File

@ -35,6 +35,11 @@ public class NavBarPosition {
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;
}