Merge "Detects nav bar gestures to progress through Home tutorial." into ub-launcher3-rvc-dev
This commit is contained in:
commit
acafb3a287
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue