Merge "Adds Assistant Sandbox tutorial." into ub-launcher3-rvc-dev
This commit is contained in:
commit
ad6a4dceea
|
@ -134,6 +134,17 @@
|
|||
<!-- Feedback shown during interactive parts of Overview gesture tutorial when the gesture is horizontal instead of vertical. [CHAR LIMIT=100] -->
|
||||
<string name="overview_gesture_feedback_wrong_swipe_direction" translatable="false">Make sure you swipe straight up and pause</string>
|
||||
|
||||
<!-- Title shown during interactive part of Assistant gesture tutorial. [CHAR LIMIT=30] -->
|
||||
<string name="assistant_gesture_tutorial_playground_title" translatable="false">Tutorial: Assistant</string>
|
||||
<!-- Subtitle shown during interactive parts of Assistant gesture tutorial. [CHAR LIMIT=60] -->
|
||||
<string name="assistant_gesture_tutorial_playground_subtitle" translatable="false">Try swiping diagonally from a bottom corner of the screen</string>
|
||||
<!-- Feedback shown during interactive parts of Assistant gesture tutorial when the gesture is started too far from the corner. [CHAR LIMIT=100] -->
|
||||
<string name="assistant_gesture_feedback_swipe_too_far_from_corner" translatable="false">Make sure you swipe from a bottom corner of the screen</string>
|
||||
<!-- Feedback shown during interactive parts of Assistant gesture tutorial when the gesture doesn't go diagonally enough. [CHAR LIMIT=100] -->
|
||||
<string name="assistant_gesture_feedback_swipe_not_diagonal" translatable="false">Make sure you swipe diagonally</string>
|
||||
<!-- Feedback shown during interactive parts of Assistant gesture tutorial when the gesture doesn't go far enough. [CHAR LIMIT=100] -->
|
||||
<string name="assistant_gesture_feedback_swipe_not_long_enough" translatable="false">Try swiping further</string>
|
||||
|
||||
<!-- Title shown on the confirmation screen after successful gesture. [CHAR LIMIT=30] -->
|
||||
<string name="gesture_tutorial_confirm_title" translatable="false">All set</string>
|
||||
<!-- Button text shown on a button on the confirm screen to leave the tutorial. [CHAR LIMIT=14] -->
|
||||
|
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* 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.TutorialController.TutorialType.ASSISTANT_COMPLETE;
|
||||
|
||||
import android.graphics.PointF;
|
||||
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 Assistant tutorial. */
|
||||
final class AssistantGestureTutorialController extends TutorialController {
|
||||
|
||||
AssistantGestureTutorialController(AssistantGestureTutorialFragment fragment,
|
||||
TutorialType tutorialType) {
|
||||
super(fragment, tutorialType);
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getTitleStringId() {
|
||||
switch (mTutorialType) {
|
||||
case ASSISTANT:
|
||||
return R.string.assistant_gesture_tutorial_playground_title;
|
||||
case ASSISTANT_COMPLETE:
|
||||
return R.string.gesture_tutorial_confirm_title;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getSubtitleStringId() {
|
||||
if (mTutorialType == TutorialType.ASSISTANT) {
|
||||
return R.string.assistant_gesture_tutorial_playground_subtitle;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer getActionButtonStringId() {
|
||||
if (mTutorialType == ASSISTANT_COMPLETE) {
|
||||
return R.string.gesture_tutorial_action_button_label_done;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
void onActionButtonClicked(View button) {
|
||||
mTutorialFragment.closeTutorial();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackGestureAttempted(BackGestureResult result) {
|
||||
switch (mTutorialType) {
|
||||
case ASSISTANT:
|
||||
switch (result) {
|
||||
case BACK_COMPLETED_FROM_LEFT:
|
||||
case BACK_COMPLETED_FROM_RIGHT:
|
||||
case BACK_CANCELLED_FROM_LEFT:
|
||||
case BACK_CANCELLED_FROM_RIGHT:
|
||||
showFeedback(R.string.assistant_gesture_feedback_swipe_too_far_from_corner);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ASSISTANT_COMPLETE:
|
||||
if (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT
|
||||
|| result == BackGestureResult.BACK_COMPLETED_FROM_RIGHT) {
|
||||
mTutorialFragment.closeTutorial();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
|
||||
switch (mTutorialType) {
|
||||
case ASSISTANT:
|
||||
switch (result) {
|
||||
case HOME_GESTURE_COMPLETED:
|
||||
case OVERVIEW_GESTURE_COMPLETED:
|
||||
case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
|
||||
case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE:
|
||||
case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
|
||||
case HOME_OR_OVERVIEW_CANCELLED:
|
||||
showFeedback(R.string.assistant_gesture_feedback_swipe_too_far_from_corner);
|
||||
break;
|
||||
case ASSISTANT_COMPLETED:
|
||||
hideFeedback();
|
||||
hideHandCoachingAnimation();
|
||||
showRippleEffect(
|
||||
() -> mTutorialFragment.changeController(ASSISTANT_COMPLETE));
|
||||
break;
|
||||
case ASSISTANT_NOT_STARTED_BAD_ANGLE:
|
||||
showFeedback(R.string.assistant_gesture_feedback_swipe_not_diagonal);
|
||||
break;
|
||||
case ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT:
|
||||
showFeedback(R.string.assistant_gesture_feedback_swipe_not_long_enough);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ASSISTANT_COMPLETE:
|
||||
if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) {
|
||||
mTutorialFragment.closeTutorial();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAssistantProgress(float progress) {
|
||||
// TODO: Create an animation.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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 android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.interaction.TutorialController.TutorialType;
|
||||
|
||||
/** Shows the Home gesture interactive tutorial. */
|
||||
public class AssistantGestureTutorialFragment extends TutorialFragment {
|
||||
@Override
|
||||
int getHandAnimationResId() {
|
||||
return R.drawable.assistant_gesture;
|
||||
}
|
||||
|
||||
@Override
|
||||
TutorialController createController(TutorialType type) {
|
||||
return new AssistantGestureTutorialController(this, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
Class<? extends TutorialController> getControllerClass() {
|
||||
return AssistantGestureTutorialController.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN && mTutorialController != null) {
|
||||
mTutorialController.setRippleHotspot(motionEvent.getX(), motionEvent.getY());
|
||||
}
|
||||
return super.onTouch(view, motionEvent);
|
||||
}
|
||||
}
|
|
@ -21,8 +21,6 @@ import static com.android.quickstep.interaction.TutorialController.TutorialType.
|
|||
import android.graphics.PointF;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
|
||||
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
|
||||
|
@ -156,7 +154,4 @@ final class BackGestureTutorialController extends TutorialController {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNavBarGestureProgress(@Nullable Float displacement) {}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
*/
|
||||
package com.android.quickstep.interaction;
|
||||
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_COMPLETED;
|
||||
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_BAD_ANGLE;
|
||||
import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult.ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT;
|
||||
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_CANCELLED;
|
||||
|
@ -22,38 +26,69 @@ import static com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestu
|
|||
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.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.os.SystemClock;
|
||||
import android.view.Display;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.Surface;
|
||||
import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.ViewConfiguration;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ResourceUtils;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.util.NavBarPosition;
|
||||
import com.android.quickstep.util.TriggerSwipeUpTouchTracker;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
|
||||
/** Utility class to handle home gestures. */
|
||||
/** Utility class to handle Home and Assistant gestures. */
|
||||
public class NavBarGestureHandler implements OnTouchListener,
|
||||
TriggerSwipeUpTouchTracker.OnSwipeUpListener {
|
||||
|
||||
private static final String LOG_TAG = "NavBarGestureHandler";
|
||||
private static final long RETRACT_GESTURE_ANIMATION_DURATION_MS = 300;
|
||||
|
||||
private final Context mContext;
|
||||
private final Point mDisplaySize = new Point();
|
||||
private final TriggerSwipeUpTouchTracker mSwipeUpTouchTracker;
|
||||
private int mBottomGestureHeight;
|
||||
private final int mBottomGestureHeight;
|
||||
private final GestureDetector mAssistantGestureDetector;
|
||||
private final int mAssistantAngleThreshold;
|
||||
private final RectF mAssistantLeftRegion = new RectF();
|
||||
private final RectF mAssistantRightRegion = new RectF();
|
||||
private final float mAssistantDragDistThreshold;
|
||||
private final float mAssistantFlingDistThreshold;
|
||||
private final long mAssistantTimeThreshold;
|
||||
private final float mAssistantSquaredSlop;
|
||||
private final PointF mAssistantStartDragPos = new PointF();
|
||||
private final PointF mDownPos = new PointF();
|
||||
private final PointF mLastPos = new PointF();
|
||||
private boolean mTouchCameFromAssistantCorner;
|
||||
private boolean mTouchCameFromNavBar;
|
||||
private float mDownY;
|
||||
private boolean mPassedAssistantSlop;
|
||||
private boolean mAssistantGestureActive;
|
||||
private boolean mLaunchedAssistant;
|
||||
private long mAssistantDragStartTime;
|
||||
private float mAssistantDistance;
|
||||
private float mAssistantTimeFraction;
|
||||
private float mAssistantLastProgress;
|
||||
@Nullable
|
||||
private NavBarGestureAttemptCallback mGestureCallback;
|
||||
|
||||
NavBarGestureHandler(Context context) {
|
||||
final Display display = context.getDisplay();
|
||||
mContext = context;
|
||||
final Display display = mContext.getDisplay();
|
||||
final int displayRotation;
|
||||
if (display == null) {
|
||||
displayRotation = Surface.ROTATION_0;
|
||||
|
@ -61,7 +96,6 @@ public class NavBarGestureHandler implements OnTouchListener,
|
|||
displayRotation = display.getRotation();
|
||||
display.getRealSize(mDisplaySize);
|
||||
}
|
||||
mDownY = mDisplaySize.y;
|
||||
mSwipeUpTouchTracker =
|
||||
new TriggerSwipeUpTouchTracker(context, true /*disableHorizontalSwipe*/,
|
||||
new NavBarPosition(Mode.NO_BUTTON, displayRotation),
|
||||
|
@ -70,6 +104,27 @@ public class NavBarGestureHandler implements OnTouchListener,
|
|||
final Resources resources = context.getResources();
|
||||
mBottomGestureHeight =
|
||||
ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE, resources);
|
||||
mAssistantDragDistThreshold =
|
||||
resources.getDimension(R.dimen.gestures_assistant_drag_threshold);
|
||||
mAssistantFlingDistThreshold =
|
||||
resources.getDimension(R.dimen.gestures_assistant_fling_threshold);
|
||||
mAssistantTimeThreshold =
|
||||
resources.getInteger(R.integer.assistant_gesture_min_time_threshold);
|
||||
mAssistantAngleThreshold =
|
||||
resources.getInteger(R.integer.assistant_gesture_corner_deg_threshold);
|
||||
|
||||
mAssistantGestureDetector = new GestureDetector(context, new AssistantGestureListener());
|
||||
int assistantWidth = resources.getDimensionPixelSize(R.dimen.gestures_assistant_width);
|
||||
final float assistantHeight = Math.max(mBottomGestureHeight,
|
||||
QuickStepContract.getWindowCornerRadius(resources));
|
||||
mAssistantLeftRegion.bottom = mAssistantRightRegion.bottom = mDisplaySize.y;
|
||||
mAssistantLeftRegion.top = mAssistantRightRegion.top = mDisplaySize.y - assistantHeight;
|
||||
mAssistantLeftRegion.left = 0;
|
||||
mAssistantLeftRegion.right = assistantWidth;
|
||||
mAssistantRightRegion.right = mDisplaySize.x;
|
||||
mAssistantRightRegion.left = mDisplaySize.x - assistantWidth;
|
||||
float slop = ViewConfiguration.get(context).getScaledTouchSlop();
|
||||
mAssistantSquaredSlop = slop * slop;
|
||||
}
|
||||
|
||||
void registerNavBarGestureAttemptCallback(NavBarGestureAttemptCallback callback) {
|
||||
|
@ -82,7 +137,7 @@ public class NavBarGestureHandler implements OnTouchListener,
|
|||
|
||||
@Override
|
||||
public void onSwipeUp(boolean wasFling, PointF finalVelocity) {
|
||||
if (mGestureCallback == null) {
|
||||
if (mGestureCallback == null || mAssistantGestureActive) {
|
||||
return;
|
||||
}
|
||||
finalVelocity.set(finalVelocity.x / 1000, finalVelocity.y / 1000);
|
||||
|
@ -98,36 +153,128 @@ public class NavBarGestureHandler implements OnTouchListener,
|
|||
|
||||
@Override
|
||||
public void onSwipeUpCancelled() {
|
||||
if (mGestureCallback != null) {
|
||||
if (mGestureCallback != null && !mAssistantGestureActive) {
|
||||
mGestureCallback.onNavBarGestureAttempted(HOME_OR_OVERVIEW_CANCELLED, new PointF());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View view, MotionEvent motionEvent) {
|
||||
int action = motionEvent.getAction();
|
||||
public boolean onTouch(View view, MotionEvent event) {
|
||||
int action = event.getAction();
|
||||
boolean intercepted = mSwipeUpTouchTracker.interceptedTouch();
|
||||
if (action == MotionEvent.ACTION_DOWN) {
|
||||
mDownY = motionEvent.getY();
|
||||
mTouchCameFromNavBar = mDownY >= mDisplaySize.y - mBottomGestureHeight;
|
||||
if (!mTouchCameFromNavBar) {
|
||||
mGestureCallback.setNavBarGestureProgress(null);
|
||||
}
|
||||
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, new PointF());
|
||||
intercepted = true;
|
||||
}
|
||||
switch (action) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mDownPos.set(event.getX(), event.getY());
|
||||
mLastPos.set(mDownPos);
|
||||
mTouchCameFromAssistantCorner =
|
||||
mAssistantLeftRegion.contains(event.getX(), event.getY())
|
||||
|| mAssistantRightRegion.contains(event.getX(), event.getY());
|
||||
mAssistantGestureActive = mTouchCameFromAssistantCorner;
|
||||
mTouchCameFromNavBar = !mTouchCameFromAssistantCorner
|
||||
&& mDownPos.y >= mDisplaySize.y - mBottomGestureHeight;
|
||||
if (!mTouchCameFromNavBar && mGestureCallback != null) {
|
||||
mGestureCallback.setNavBarGestureProgress(null);
|
||||
}
|
||||
mLaunchedAssistant = false;
|
||||
mSwipeUpTouchTracker.init();
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (!mAssistantGestureActive) {
|
||||
break;
|
||||
}
|
||||
mLastPos.set(event.getX(), event.getY());
|
||||
|
||||
if (!mPassedAssistantSlop) {
|
||||
// Normal gesture, ensure we pass the slop before we start tracking the gesture
|
||||
if (squaredHypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y)
|
||||
> mAssistantSquaredSlop) {
|
||||
|
||||
mPassedAssistantSlop = true;
|
||||
mAssistantStartDragPos.set(mLastPos.x, mLastPos.y);
|
||||
mAssistantDragStartTime = SystemClock.uptimeMillis();
|
||||
|
||||
mAssistantGestureActive = isValidAssistantGestureAngle(
|
||||
mDownPos.x - mLastPos.x, mDownPos.y - mLastPos.y);
|
||||
if (!mAssistantGestureActive && mGestureCallback != null) {
|
||||
mGestureCallback.onNavBarGestureAttempted(
|
||||
ASSISTANT_NOT_STARTED_BAD_ANGLE, new PointF());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Movement
|
||||
mAssistantDistance = (float) Math.hypot(mLastPos.x - mAssistantStartDragPos.x,
|
||||
mLastPos.y - mAssistantStartDragPos.y);
|
||||
if (mAssistantDistance >= 0) {
|
||||
final long diff = SystemClock.uptimeMillis() - mAssistantDragStartTime;
|
||||
mAssistantTimeFraction = Math.min(diff * 1f / mAssistantTimeThreshold, 1);
|
||||
updateAssistantProgress();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
if (mGestureCallback != null && !intercepted && mTouchCameFromNavBar) {
|
||||
mGestureCallback.onNavBarGestureAttempted(
|
||||
HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION, new PointF());
|
||||
intercepted = true;
|
||||
break;
|
||||
}
|
||||
if (mAssistantGestureActive && !mLaunchedAssistant && mGestureCallback != null) {
|
||||
mGestureCallback.onNavBarGestureAttempted(
|
||||
ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT, new PointF());
|
||||
ValueAnimator animator = ValueAnimator.ofFloat(mAssistantLastProgress, 0)
|
||||
.setDuration(RETRACT_GESTURE_ANIMATION_DURATION_MS);
|
||||
animator.addUpdateListener(valueAnimator -> {
|
||||
float progress = (float) valueAnimator.getAnimatedValue();
|
||||
mGestureCallback.setAssistantProgress(progress);
|
||||
});
|
||||
animator.setInterpolator(Interpolators.DEACCEL_2);
|
||||
animator.start();
|
||||
}
|
||||
mPassedAssistantSlop = false;
|
||||
break;
|
||||
}
|
||||
if (mTouchCameFromNavBar && mGestureCallback != null) {
|
||||
mGestureCallback.setNavBarGestureProgress(motionEvent.getY() - mDownY);
|
||||
mGestureCallback.setNavBarGestureProgress(event.getY() - mDownPos.y);
|
||||
}
|
||||
mSwipeUpTouchTracker.onMotionEvent(motionEvent);
|
||||
mSwipeUpTouchTracker.onMotionEvent(event);
|
||||
mAssistantGestureDetector.onTouchEvent(event);
|
||||
return intercepted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if angle is larger than threshold for assistant detection
|
||||
*/
|
||||
private boolean isValidAssistantGestureAngle(float deltaX, float deltaY) {
|
||||
float angle = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
|
||||
|
||||
// normalize so that angle is measured clockwise from horizontal in the bottom right corner
|
||||
// and counterclockwise from horizontal in the bottom left corner
|
||||
angle = angle > 90 ? 180 - angle : angle;
|
||||
return (angle > mAssistantAngleThreshold && angle < 90);
|
||||
}
|
||||
|
||||
private void updateAssistantProgress() {
|
||||
if (!mLaunchedAssistant) {
|
||||
mAssistantLastProgress =
|
||||
Math.min(mAssistantDistance * 1f / mAssistantDragDistThreshold, 1)
|
||||
* mAssistantTimeFraction;
|
||||
if (mAssistantDistance >= mAssistantDragDistThreshold && mAssistantTimeFraction >= 1) {
|
||||
startAssistant(new PointF());
|
||||
} else if (mGestureCallback != null) {
|
||||
mGestureCallback.setAssistantProgress(mAssistantLastProgress);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void startAssistant(PointF velocity) {
|
||||
if (mGestureCallback != null) {
|
||||
mGestureCallback.onNavBarGestureAttempted(ASSISTANT_COMPLETED, velocity);
|
||||
}
|
||||
VibratorWrapper.INSTANCE.get(mContext).vibrate(VibratorWrapper.EFFECT_CLICK);
|
||||
mLaunchedAssistant = true;
|
||||
}
|
||||
|
||||
enum NavBarGestureResult {
|
||||
UNKNOWN,
|
||||
HOME_GESTURE_COMPLETED,
|
||||
|
@ -135,7 +282,10 @@ public class NavBarGestureHandler implements OnTouchListener,
|
|||
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.
|
||||
HOME_OR_OVERVIEW_CANCELLED
|
||||
HOME_OR_OVERVIEW_CANCELLED,
|
||||
ASSISTANT_COMPLETED,
|
||||
ASSISTANT_NOT_STARTED_BAD_ANGLE,
|
||||
ASSISTANT_NOT_STARTED_SWIPE_TOO_SHORT,
|
||||
}
|
||||
|
||||
/** Callback to let the UI react to attempted nav bar gestures. */
|
||||
|
@ -144,6 +294,28 @@ public class NavBarGestureHandler implements OnTouchListener,
|
|||
void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity);
|
||||
|
||||
/** Indicates how far a touch originating in the nav bar has moved from the nav bar. */
|
||||
void setNavBarGestureProgress(@Nullable Float displacement);
|
||||
default void setNavBarGestureProgress(@Nullable Float displacement) {}
|
||||
|
||||
/** Indicates the progress of an Assistant gesture. */
|
||||
default void setAssistantProgress(float progress) {}
|
||||
}
|
||||
|
||||
private class AssistantGestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||
@Override
|
||||
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||
if (!mLaunchedAssistant && mTouchCameFromAssistantCorner) {
|
||||
PointF velocity = new PointF(velocityX, velocityY);
|
||||
if (!isValidAssistantGestureAngle(velocityX, -velocityY)) {
|
||||
if (mGestureCallback != null) {
|
||||
mGestureCallback.onNavBarGestureAttempted(ASSISTANT_NOT_STARTED_BAD_ANGLE,
|
||||
velocity);
|
||||
}
|
||||
} else if (mAssistantDistance >= mAssistantFlingDistThreshold) {
|
||||
mAssistantLastProgress = 1;
|
||||
startAssistant(velocity);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -202,7 +202,8 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
private boolean isComplete() {
|
||||
return mTutorialType == TutorialType.BACK_NAVIGATION_COMPLETE
|
||||
|| mTutorialType == TutorialType.HOME_NAVIGATION_COMPLETE
|
||||
|| mTutorialType == TutorialType.OVERVIEW_NAVIGATION_COMPLETE;
|
||||
|| mTutorialType == TutorialType.OVERVIEW_NAVIGATION_COMPLETE
|
||||
|| mTutorialType == TutorialType.ASSISTANT_COMPLETE;
|
||||
}
|
||||
|
||||
/** Denotes the type of the tutorial. */
|
||||
|
@ -213,6 +214,8 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
|||
HOME_NAVIGATION,
|
||||
HOME_NAVIGATION_COMPLETE,
|
||||
OVERVIEW_NAVIGATION,
|
||||
OVERVIEW_NAVIGATION_COMPLETE
|
||||
OVERVIEW_NAVIGATION_COMPLETE,
|
||||
ASSISTANT,
|
||||
ASSISTANT_COMPLETE
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,6 +71,9 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
|||
case OVERVIEW_NAVIGATION:
|
||||
case OVERVIEW_NAVIGATION_COMPLETE:
|
||||
return new OverviewGestureTutorialFragment();
|
||||
case ASSISTANT:
|
||||
case ASSISTANT_COMPLETE:
|
||||
return new AssistantGestureTutorialFragment();
|
||||
default:
|
||||
Log.e(LOG_TAG, "Failed to find an appropriate fragment for " + tutorialType.name());
|
||||
}
|
||||
|
|
|
@ -246,6 +246,15 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
|
|||
return true;
|
||||
});
|
||||
sandboxCategory.addPreference(launchOverviewTutorialPreference);
|
||||
Preference launchAssistantTutorialPreference = new Preference(context);
|
||||
launchAssistantTutorialPreference.setKey("launchAssistantTutorial");
|
||||
launchAssistantTutorialPreference.setTitle("Launch Assistant Tutorial");
|
||||
launchAssistantTutorialPreference.setSummary("Learn how to use the Assistant gesture");
|
||||
launchAssistantTutorialPreference.setOnPreferenceClickListener(preference -> {
|
||||
startActivity(launchSandboxIntent.putExtra("tutorial_type", "ASSISTANT"));
|
||||
return true;
|
||||
});
|
||||
sandboxCategory.addPreference(launchAssistantTutorialPreference);
|
||||
}
|
||||
|
||||
private String toName(String action) {
|
||||
|
|
Loading…
Reference in New Issue