Updating overview tutorial to new simple tutorial flow

test: built and tested on multiple devices. recorded videos and shared in chat.

bug: b/253520701, b/253521660, b/241813570

Change-Id: I57f88f5fb35c6a7b1219fac6e992bb84354b91ef
This commit is contained in:
randypfohl 2023-03-20 13:15:03 -07:00 committed by Randy Pfohl
parent fad8c1c449
commit 1c0a27a28e
9 changed files with 142 additions and 13 deletions

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023 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.
-->
<View
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/overview_gesture_tutorial_shape"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="@color/gesture_overview_tutorial_background" />

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -47,7 +47,9 @@
<color name="gesture_home_tutorial_swipe_up_rect">#3857C7</color>
<color name="gesture_back_tutorial_exiting_app">#F3A5B9</color>
<color name="gesture_back_tutorial_background">#3857C7</color>
<color name="gesture_overview_tutorial_background">#E2F3AF</color>
<color name="gesture_overview_tutorial_swipe_rect">#7E44AD</color>
<color name="gesture_overview_background">#BFC8CB</color>
<!-- Mock hotseat -->
<color name="mock_app_icon">#BDC1C6</color>

View File

@ -156,6 +156,8 @@
<string name="overview_gesture_intro_subtitle">To switch between apps, swipe up from the bottom of your screen, hold, then release.</string>
<!-- Introduction subtitle for the Overview gesture tutorial that will be spoken by screen readers. [CHAR LIMIT=100] -->
<string name="overview_gesture_spoken_intro_subtitle">To switch between apps, swipe up with 2 fingers from the bottom of your screen, hold, then release.</string>
<!-- Title of the gesture tutorial section educating users on how to switch between apps. [CHAR LIMIT=100] -->
<string name="overview_gesture_tutorial_title">Switch apps</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>

View File

@ -15,6 +15,8 @@
*/
package com.android.quickstep.interaction;
import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
@ -22,11 +24,16 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.ColorInt;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.Outline;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.ViewAnimator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -85,6 +92,45 @@ public class AnimatedTaskView extends ConstraintLayout {
setToSingleRowLayout(false);
}
void animateToFillScreen(@Nullable Runnable onAnimationEndCallback) {
AnimatorSet set = new AnimatorSet();
ArrayList<Animator> animations = new ArrayList<>();
// center view
animations.add(ObjectAnimator.ofFloat(this, TRANSLATION_X, 0));
// calculate full screen scaling, scale should be 1:1 for x and y
Matrix matrix = getAnimationMatrix();
float[] matrixValues = new float[9];
matrix.getValues(matrixValues);
float scaleX = matrixValues[Matrix.MSCALE_X];
float scaleToFullScreen = 1 / scaleX;
// scale view to full screen
ValueAnimator scale = ValueAnimator.ofFloat(1f, scaleToFullScreen);
scale.addUpdateListener(animation -> {
float value = (float) animation.getAnimatedValue();
mFullTaskView.setScaleX(value);
mFullTaskView.setScaleY(value);
});
animations.add(scale);
set.playSequentially(animations);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
if (onAnimationEndCallback != null) {
onAnimationEndCallback.run();
}
}
});
set.start();
}
AnimatorSet createAnimationToMultiRowLayout() {
if (mTaskViewOutlineProvider == null) {
// This is an illegal state.
@ -184,6 +230,11 @@ public class AnimatedTaskView extends ConstraintLayout {
void setFakeTaskViewFillColor(@ColorInt int colorResId) {
mFullTaskView.setBackgroundColor(colorResId);
if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()){
mTopTaskView.getBackground().setTint(colorResId);
mBottomTaskView.getBackground().setTint(colorResId);
}
}
@Override

View File

@ -16,12 +16,17 @@
package com.android.quickstep.interaction;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.annotation.Nullable;
import android.annotation.TargetApi;
import android.graphics.PointF;
import android.os.Build;
import android.os.Handler;
import android.view.View;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
@ -40,10 +45,11 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
TutorialType tutorialType) {
super(fragment, tutorialType);
}
@Override
public int getIntroductionTitle() {
return R.string.overview_gesture_intro_title;
return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.string.overview_gesture_tutorial_title
: R.string.overview_gesture_intro_title;
}
@Override
@ -65,19 +71,29 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
@Override
protected int getMockAppTaskLayoutResId() {
return mTutorialFragment.isLargeScreen()
? R.layout.gesture_tutorial_tablet_mock_conversation_list
: R.layout.gesture_tutorial_mock_conversation_list;
return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.layout.gesture_tutorial_mock_task_view
: mTutorialFragment.isLargeScreen()
? R.layout.gesture_tutorial_tablet_mock_conversation_list
: R.layout.gesture_tutorial_mock_conversation_list;
}
@Override
protected int getGestureLottieAnimationId() {
// TODO(b/253521660): Change to correct LottieAnimationView
return R.raw.home_gesture_tutorial_animation;
return mTutorialFragment.isLargeScreen()
? R.raw.overview_gesture_tutorial_tablet_animation
: R.raw.overview_gesture_tutorial_animation;
}
@Override
protected int getSwipeActionColorResId() {
return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.color.gesture_overview_background
: R.color.gesture_overview_tutorial_swipe_rect;
}
@Override
protected int getMockPreviousAppTaskThumbnailColorResId() {
return R.color.gesture_overview_tutorial_swipe_rect;
}
@ -127,9 +143,31 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
break;
case OVERVIEW_GESTURE_COMPLETED:
mTutorialFragment.releaseFeedbackAnimation();
animateTaskViewToOverview();
onMotionPaused(true /*arbitrary value*/);
showSuccessFeedback();
if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
onMotionPaused(true /*arbitrary value*/);
animateTaskViewToOverview(() -> {
mFakeTaskView.setVisibility(View.INVISIBLE);
if(!mTutorialFragment.isLargeScreen()){
mFakePreviousTaskView.animateToFillScreen(() -> {
mFakeLauncherView.setBackgroundColor(
mContext.getColor(
R.color.gesture_overview_tutorial_swipe_rect
));
showSuccessFeedback();
});
} else {
mFakeLauncherView.setBackgroundColor(
mContext.getColor(
R.color.gesture_overview_tutorial_swipe_rect
));
showSuccessFeedback();
}
});
} else {
animateTaskViewToOverview(null);
onMotionPaused(true /*arbitrary value*/);
showSuccessFeedback();
}
break;
case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:
case HOME_OR_OVERVIEW_CANCELLED:
@ -146,11 +184,24 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
}
}
public void animateTaskViewToOverview() {
/**
* runnable executed with slight delay to ease the swipe animation after landing on overview
* @param runnable
*/
public void animateTaskViewToOverview(@Nullable Runnable runnable) {
PendingAnimation anim = new PendingAnimation(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
anim.setFloat(mTaskViewSwipeUpAnimation
.getCurrentShift(), AnimatedFloat.VALUE, 1, ACCEL);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
if (runnable != null) {
new Handler().postDelayed(runnable, 300);
}
}
});
ArrayList<Animator> animators = new ArrayList<>();
if (mTutorialFragment.isLargeScreen()) {

View File

@ -67,7 +67,7 @@ public class OverviewGestureTutorialFragment extends TutorialFragment {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
controller.animateTaskViewToOverview();
controller.animateTaskViewToOverview(null);
}
});

View File

@ -678,7 +678,8 @@ abstract class TutorialController implements BackGestureAttemptCallback,
? R.dimen.gesture_tutorial_tablet_feedback_margin_top
: R.dimen.gesture_tutorial_feedback_margin_top);
mFakeTaskbarView.setVisibility(mTutorialFragment.isLargeScreen() ? View.VISIBLE : GONE);
mFakeTaskbarView.setVisibility((mTutorialFragment.isLargeScreen()
&& !ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) ? View.VISIBLE : GONE);
RelativeLayout.LayoutParams hotseatLayoutParams =
(RelativeLayout.LayoutParams) mFakeHotseatView.getLayoutParams();