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:
parent
fad8c1c449
commit
1c0a27a28e
|
@ -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
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -67,7 +67,7 @@ public class OverviewGestureTutorialFragment extends TutorialFragment {
|
|||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
super.onAnimationStart(animation);
|
||||
controller.animateTaskViewToOverview();
|
||||
controller.animateTaskViewToOverview(null);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue