Merge "Redesign the tutorial for the go home gesture" into tm-qpr-dev am: 334094da9e

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/21150239

Change-Id: Ic9945132bfd6c048136dea36abbfcb846750d954
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Saumya Prakash
2023-02-02 22:12:23 +00:00
committed by Automerger Merge Worker
15 changed files with 604 additions and 14 deletions
@@ -59,6 +59,12 @@ final class BackGestureTutorialController extends TutorialController {
return getMockAppTaskCurrentPageLayoutResId();
}
@Override
protected int getGestureLottieAnimationId() {
// TODO(b/253521922): Change to correct LottieAnimationView
return R.raw.home_gesture_tutorial_animation;
}
@LayoutRes
int getMockAppTaskCurrentPageLayoutResId() {
return mTutorialFragment.isLargeScreen()
@@ -73,6 +79,11 @@ final class BackGestureTutorialController extends TutorialController {
: R.layout.gesture_tutorial_mock_conversation_list;
}
@Override
protected int getSwipeActionColorResId() {
return R.color.gesture_back_tutorial_swipe_rect;
}
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (isGestureCompleted()) {
@@ -15,6 +15,8 @@
*/
package com.android.quickstep.interaction;
import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL;
import android.annotation.TargetApi;
import android.graphics.PointF;
import android.os.Build;
@@ -33,12 +35,16 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
@Override
public int getIntroductionTitle() {
return R.string.home_gesture_intro_title;
return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.string.home_gesture_tutorial_title
: R.string.home_gesture_intro_title;
}
@Override
public int getIntroductionSubtitle() {
return R.string.home_gesture_intro_subtitle;
return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.string.home_gesture_tutorial_subtitle
: R.string.home_gesture_intro_subtitle;
}
@Override
@@ -57,7 +63,19 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
protected int getMockAppTaskLayoutResId() {
return mTutorialFragment.isLargeScreen()
? R.layout.gesture_tutorial_tablet_mock_webpage
: R.layout.gesture_tutorial_mock_webpage;
: ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.layout.swipe_up_gesture_tutorial_shape
: R.layout.gesture_tutorial_mock_webpage;
}
@Override
protected int getGestureLottieAnimationId() {
return R.raw.home_gesture_tutorial_animation;
}
@Override
protected int getSwipeActionColorResId() {
return R.color.gesture_home_tutorial_swipe_up_rect;
}
@Override
@@ -70,6 +70,17 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
: 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;
}
@Override
protected int getSwipeActionColorResId() {
return R.color.gesture_overview_tutorial_swipe_rect;
}
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (isGestureCompleted()) {
@@ -19,12 +19,15 @@ import static android.view.View.GONE;
import static android.view.View.NO_ID;
import static android.view.View.inflate;
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.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.ColorRes;
import android.annotation.RawRes;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.AnimatedVectorDrawable;
@@ -57,6 +60,8 @@ import com.android.launcher3.views.ClipIconView;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureAttemptCallback;
import com.airbnb.lottie.LottieAnimationView;
import java.util.ArrayList;
abstract class TutorialController implements BackGestureAttemptCallback,
@@ -85,6 +90,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
final Button mDoneButton;
final ViewGroup mFeedbackView;
final TextView mFeedbackTitleView;
final TextView mFeedbackSubtitleView;
final ImageView mEdgeGestureVideoView;
final RelativeLayout mFakeLauncherView;
final FrameLayout mFakeHotseatView;
@@ -100,6 +106,8 @@ abstract class TutorialController implements BackGestureAttemptCallback,
private final AlertDialog mSkipTutorialDialog;
private boolean mGestureCompleted = false;
private LottieAnimationView mAnimatedGestureDemonstration;
private RelativeLayout mFullGestureDemonstration;
// These runnables should be used when posting callbacks to their views and cleared from their
// views before posting new callbacks.
@@ -120,6 +128,8 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mFeedbackView = rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_view);
mFeedbackTitleView = mFeedbackView.findViewById(
R.id.gesture_tutorial_fragment_feedback_title);
mFeedbackSubtitleView = mFeedbackView.findViewById(
R.id.gesture_tutorial_fragment_feedback_subtitle);
mEdgeGestureVideoView = rootView.findViewById(R.id.gesture_tutorial_edge_gesture_video);
mFakeLauncherView = rootView.findViewById(R.id.gesture_tutorial_fake_launcher_view);
mFakeHotseatView = rootView.findViewById(R.id.gesture_tutorial_fake_hotseat_view);
@@ -136,6 +146,17 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mFingerDotView = rootView.findViewById(R.id.gesture_tutorial_finger_dot);
mSkipTutorialDialog = createSkipTutorialDialog();
if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
mAnimatedGestureDemonstration = mTutorialFragment.getRootView().findViewById(
R.id.gesture_demonstration_animations);
mFullGestureDemonstration = mTutorialFragment.getRootView().findViewById(
R.id.full_gesture_demonstration);
mFeedbackTitleView.setText(getIntroductionTitle());
mFeedbackSubtitleView.setText(getIntroductionSubtitle());
mSkipButton.setVisibility(GONE);
}
mTitleViewCallback = () -> mFeedbackTitleView.sendAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_FOCUSED);
mShowFeedbackRunnable = () -> {
@@ -189,12 +210,19 @@ abstract class TutorialController implements BackGestureAttemptCallback,
? (mTutorialFragment.isFoldable()
? R.layout.gesture_tutorial_foldable_mock_hotseat
: R.layout.gesture_tutorial_tablet_mock_hotseat)
: R.layout.gesture_tutorial_mock_hotseat;
: (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.layout.redesigned_gesture_tutorial_mock_hotseat
: R.layout.gesture_tutorial_mock_hotseat);
}
@LayoutRes
protected int getMockAppTaskLayoutResId() {
return View.NO_ID;
return NO_ID;
}
@RawRes
protected int getGestureLottieAnimationId() {
return NO_ID;
}
@ColorRes
@@ -202,9 +230,16 @@ abstract class TutorialController implements BackGestureAttemptCallback,
return R.color.gesture_tutorial_fake_previous_task_view_color;
}
@ColorRes
protected int getSwipeActionColorResId() {
return NO_ID;
}
@DrawableRes
public int getMockAppIconResId() {
return R.drawable.default_sandbox_app_icon;
return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.drawable.redesigned_default_sandbox_app_icon
: R.drawable.default_sandbox_app_icon;
}
@DrawableRes
@@ -301,9 +336,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
}
mFeedbackTitleView.setText(titleResId);
TextView subtitle =
mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_subtitle);
subtitle.setText(spokenSubtitleResId == NO_ID
mFeedbackSubtitleView.setText(spokenSubtitleResId == NO_ID
? mContext.getText(subtitleResId)
: Utilities.wrapForTts(
mContext.getText(subtitleResId), mContext.getString(spokenSubtitleResId)));
@@ -316,6 +349,10 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mFakeTaskView.removeCallbacks(mFakeTaskViewCallback);
mFakeTaskViewCallback = null;
}
if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
showSuccessPage();
}
}
mGestureCompleted = isGestureSuccessful;
@@ -336,6 +373,16 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mFeedbackView.post(mFeedbackViewCallback);
}
private void showSuccessPage() {
mFeedbackView.findViewById(
R.id.gesture_tutorial_checkbox_bg).setVisibility(View.VISIBLE);
mFeedbackView.findViewById(
R.id.gesture_tutorial_checkbox).setVisibility(View.VISIBLE);
mFeedbackTitleView.setTextAppearance(R.style.TextAppearance_GestureTutorial_SuccessTitle);
mFeedbackSubtitleView.setTextAppearance(
R.style.TextAppearance_GestureTutorial_SuccessSubtitle);
}
public boolean isGestureCompleted() {
return mGestureCompleted;
}
@@ -371,6 +418,14 @@ abstract class TutorialController implements BackGestureAttemptCallback,
@NonNull Runnable onStartRunnable,
boolean useGestureAnimationDelay) {
if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
mFeedbackView.setVisibility(View.VISIBLE);
mAnimatedGestureDemonstration.setVisibility(View.VISIBLE);
mFullGestureDemonstration.setVisibility(View.VISIBLE);
mAnimatedGestureDemonstration.playAnimation();
return;
}
if (gestureAnimation.isRunning()) {
gestureAnimation.cancel();
}
@@ -436,19 +491,29 @@ abstract class TutorialController implements BackGestureAttemptCallback,
@CallSuper
void transitToController() {
hideFeedback();
hideActionButton();
updateCloseButton();
updateSubtext();
updateDrawables();
updateLayout();
if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
startGestureAnimation();
} else {
hideFeedback();
hideActionButton();
}
mGestureCompleted = false;
if (mFakeHotseatView != null) {
mFakeHotseatView.setVisibility(View.INVISIBLE);
}
}
private void startGestureAnimation() {
mAnimatedGestureDemonstration.setAnimation(getGestureLottieAnimationId());
mAnimatedGestureDemonstration.playAnimation();
}
void updateCloseButton() {
mSkipButton.setTextAppearance(Utilities.isDarkTheme(mContext)
? R.style.TextAppearance_GestureTutorial_Feedback_Subtext
@@ -512,8 +577,10 @@ abstract class TutorialController implements BackGestureAttemptCallback,
}
private void updateSubtext() {
mTutorialStepView.setTutorialProgress(
mTutorialFragment.getCurrentStep(), mTutorialFragment.getNumSteps());
if (!ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
mTutorialStepView.setTutorialProgress(
mTutorialFragment.getCurrentStep(), mTutorialFragment.getNumSteps());
}
}
private void updateDrawables() {
@@ -532,6 +599,11 @@ abstract class TutorialController implements BackGestureAttemptCallback,
getMockPreviousAppTaskThumbnailColorResId()));
mFakeIconView.setBackground(AppCompatResources.getDrawable(
mContext, getMockAppIconResId()));
if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
mFakeLauncherView.setBackgroundColor(
mContext.getColor(getSwipeActionColorResId()));
}
}
}
@@ -686,6 +758,12 @@ abstract class TutorialController implements BackGestureAttemptCallback,
return ValueAnimator.ofFloat(0f, 1f).setDuration(GESTURE_ANIMATION_PAUSE_DURATION_MILLIS);
}
void pauseAndHideLottieAnimation() {
mAnimatedGestureDemonstration.pauseAnimation();
mAnimatedGestureDemonstration.setVisibility(View.INVISIBLE);
mFullGestureDemonstration.setVisibility(View.INVISIBLE);
}
/** Denotes the type of the tutorial. */
enum TutorialType {
BACK_NAVIGATION,
@@ -17,6 +17,8 @@ package com.android.quickstep.interaction;
import static android.view.View.NO_ID;
import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
@@ -184,7 +186,12 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
super.onCreateView(inflater, container, savedInstanceState);
mRootView = (RootSandboxLayout) inflater.inflate(
R.layout.gesture_tutorial_fragment, container, false);
ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.layout.redesigned_gesture_tutorial_fragment
: R.layout.gesture_tutorial_fragment,
container,
false);
mRootView.setOnApplyWindowInsetsListener((view, insets) -> {
Insets systemInsets = insets.getInsets(WindowInsets.Type.systemBars());
mEdgeBackGestureHandler.setInsets(systemInsets.left, systemInsets.right);
@@ -333,6 +340,11 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
if (mTutorialController != null && !isGestureComplete()) {
mTutorialController.hideFeedback();
}
if (ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
mTutorialController.pauseAndHideLottieAnimation();
}
// Note: Using logical-or to ensure both functions get called.
return mEdgeBackGestureHandler.onTouch(view, motionEvent)
| mNavBarGestureHandler.onTouch(view, motionEvent);