From e61fd5f316fc922aec31049ffa41ab78f0b24c02 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Thu, 30 Sep 2021 15:44:33 -0700 Subject: [PATCH] Add mock animated taskbar to gesture nav tutorial for foldable devices. Bug: 198434693 Test: launched and completed tutorial on regular phone and foldable device. Change-Id: Id378e9bdd21fdfbc880ef528cb040b6390699d43 --- ...re_tutorial_foldable_mock_conversation.xml | 2 +- ...torial_foldable_mock_conversation_list.xml | 2 +- ...gesture_tutorial_foldable_mock_taskbar.xml | 118 ++++++ .../res/layout/gesture_tutorial_fragment.xml | 9 + quickstep/res/values/colors.xml | 1 + quickstep/res/values/dimens.xml | 6 + .../interaction/AnimatedTaskbarView.java | 368 ++++++++++++++++++ .../HomeGestureTutorialController.java | 6 +- .../HomeGestureTutorialFragment.java | 4 +- .../OverviewGestureTutorialController.java | 3 +- .../OverviewGestureTutorialFragment.java | 4 +- .../SwipeUpGestureTutorialController.java | 5 +- .../interaction/TutorialController.java | 41 ++ 13 files changed, 559 insertions(+), 10 deletions(-) create mode 100644 quickstep/res/layout/gesture_tutorial_foldable_mock_taskbar.xml create mode 100644 quickstep/src/com/android/quickstep/interaction/AnimatedTaskbarView.java diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml b/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml index 34bd4e2845..b0cc00ba53 100644 --- a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml +++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml @@ -84,7 +84,7 @@ android:layout_width="match_parent" android:layout_height="0dp" android:background="@color/mock_conversation_background" - android:paddingBottom="80dp" + android:paddingBottom="@dimen/gesture_tutorial_mock_taskbar_height" app:layout_constraintTop_toBottomOf="@id/top_bar" app:layout_constraintBottom_toBottomOf="parent" diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml b/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml index 0309cc37cc..e5cd9bce1e 100644 --- a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml +++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation_list.xml @@ -51,7 +51,7 @@ android:layout_width="match_parent" android:layout_height="0dp" android:background="@color/mock_list_background" - android:paddingBottom="80dp" + android:paddingBottom="@dimen/gesture_tutorial_mock_taskbar_height" app:layout_constraintTop_toBottomOf="@id/top_bar" app:layout_constraintBottom_toBottomOf="parent" diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_taskbar.xml b/quickstep/res/layout/gesture_tutorial_foldable_mock_taskbar.xml new file mode 100644 index 0000000000..ddfeeecf04 --- /dev/null +++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_taskbar.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quickstep/res/layout/gesture_tutorial_fragment.xml b/quickstep/res/layout/gesture_tutorial_fragment.xml index 41d0a1d38f..08e6178bdb 100644 --- a/quickstep/res/layout/gesture_tutorial_fragment.xml +++ b/quickstep/res/layout/gesture_tutorial_fragment.xml @@ -101,6 +101,15 @@ android:layout_height="match_parent" android:background="@drawable/gesture_tutorial_ripple"/> + + #3C4043 #FF000000 #B7F29F + #202124 #8AB4F8 diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index e08eda8d3c..bca3bc05ab 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -121,6 +121,7 @@ 140dp 72dp 18dp + 80dp 44dp @@ -155,6 +156,11 @@ 36dp 22dp + + 44dp + 100dp + 218dp + 40dp 24dp diff --git a/quickstep/src/com/android/quickstep/interaction/AnimatedTaskbarView.java b/quickstep/src/com/android/quickstep/interaction/AnimatedTaskbarView.java new file mode 100644 index 0000000000..e8cc45b97b --- /dev/null +++ b/quickstep/src/com/android/quickstep/interaction/AnimatedTaskbarView.java @@ -0,0 +1,368 @@ +/* + * Copyright (C) 2021 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.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; + +import com.android.launcher3.R; + +import java.util.ArrayList; + + +/** + * Helper View for the gesture tutorial mock taskbar view. + * + * This helper class allows animating this mock taskview to and from a mock hotseat and the bottom + * of the screen. + */ +public class AnimatedTaskbarView extends ConstraintLayout { + + private View mBackground; + private View mIconContainer; + private View mIcon1; + private View mIcon2; + private View mIcon3; + private View mIcon4; + private View mIcon5; + private View mIcon6; + + @Nullable private Animator mRunningAnimator; + + public AnimatedTaskbarView(@NonNull Context context) { + super(context); + } + + public AnimatedTaskbarView(@NonNull Context context, + @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public AnimatedTaskbarView(@NonNull Context context, @Nullable AttributeSet attrs, + int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public AnimatedTaskbarView(@NonNull Context context, @Nullable AttributeSet attrs, + int defStyleAttr, + int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + mBackground = findViewById(R.id.taskbar_background); + mIconContainer = findViewById(R.id.icon_container); + mIcon1 = findViewById(R.id.taskbar_icon_1); + mIcon2 = findViewById(R.id.taskbar_icon_2); + mIcon3 = findViewById(R.id.taskbar_icon_3); + mIcon4 = findViewById(R.id.taskbar_icon_4); + mIcon5 = findViewById(R.id.taskbar_icon_5); + mIcon6 = findViewById(R.id.taskbar_icon_6); + } + + /** + * Animates this fake taskbar's disappearance into the given hotseat view. + */ + public void animateDisappearanceToHotseat(ViewGroup hotseat) { + ArrayList animators = new ArrayList<>(); + int hotseatTop = hotseat.getTop(); + + animators.add(ObjectAnimator.ofFloat( + mBackground, View.TRANSLATION_Y, 0, mBackground.getHeight())); + animators.add(ObjectAnimator.ofFloat(mBackground, View.ALPHA, 1f, 0f)); + animators.add(createIconDisappearanceToHotseatAnimator( + mIcon1, hotseat.findViewById(R.id.hotseat_icon_1), hotseatTop)); + animators.add(createIconDisappearanceToHotseatAnimator( + mIcon2, hotseat.findViewById(R.id.hotseat_icon_2), hotseatTop)); + animators.add(createIconDisappearanceToHotseatAnimator( + mIcon3, hotseat.findViewById(R.id.hotseat_icon_3), hotseatTop)); + animators.add(createIconDisappearanceToHotseatAnimator( + mIcon4, hotseat.findViewById(R.id.hotseat_icon_4), hotseatTop)); + animators.add(createIconDisappearanceToHotseatAnimator( + mIcon5, hotseat.findViewById(R.id.hotseat_icon_5), hotseatTop)); + animators.add(createIconDisappearanceToHotseatAnimator( + mIcon6, hotseat.findViewById(R.id.hotseat_icon_6), hotseatTop)); + + AnimatorSet animatorSet = new AnimatorSet(); + + animatorSet.playTogether(animators); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + setVisibility(INVISIBLE); + } + + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + setVisibility(VISIBLE); + } + }); + + start(animatorSet); + } + + /** + * Animates this fake taskbar's appearance from the given hotseat view. + */ + public void animateAppearanceFromHotseat(ViewGroup hotseat) { + ArrayList animators = new ArrayList<>(); + int hotseatTop = hotseat.getTop(); + + animators.add(ObjectAnimator.ofFloat( + mBackground, View.TRANSLATION_Y, mBackground.getHeight(), 0)); + animators.add(ObjectAnimator.ofFloat(mBackground, View.ALPHA, 0f, 1f)); + animators.add(createIconAppearanceFromHotseatAnimator( + mIcon1, hotseat.findViewById(R.id.hotseat_icon_1), hotseatTop)); + animators.add(createIconAppearanceFromHotseatAnimator( + mIcon2, hotseat.findViewById(R.id.hotseat_icon_2), hotseatTop)); + animators.add(createIconAppearanceFromHotseatAnimator( + mIcon3, hotseat.findViewById(R.id.hotseat_icon_3), hotseatTop)); + animators.add(createIconAppearanceFromHotseatAnimator( + mIcon4, hotseat.findViewById(R.id.hotseat_icon_4), hotseatTop)); + animators.add(createIconAppearanceFromHotseatAnimator( + mIcon5, hotseat.findViewById(R.id.hotseat_icon_5), hotseatTop)); + animators.add(createIconAppearanceFromHotseatAnimator( + mIcon6, hotseat.findViewById(R.id.hotseat_icon_6), hotseatTop)); + + AnimatorSet animatorSet = new AnimatorSet(); + + animatorSet.playTogether(animators); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + setVisibility(VISIBLE); + } + }); + + start(animatorSet); + } + + /** + * Animates this fake taskbar's disappearance to the bottom of the screen. + */ + public void animateDisappearanceToBottom() { + ArrayList animators = new ArrayList<>(); + + animators.add(ObjectAnimator.ofFloat( + mBackground, View.TRANSLATION_Y, 0, mBackground.getHeight())); + animators.add(ObjectAnimator.ofFloat(mBackground, View.ALPHA, 1f, 0f)); + animators.add(ObjectAnimator.ofFloat(mIconContainer, View.SCALE_X, 1f, 0f)); + animators.add(ObjectAnimator.ofFloat(mIconContainer, View.SCALE_Y, 1f, 0f)); + + initializeIconContainerPivot(); + + AnimatorSet animatorSet = new AnimatorSet(); + + animatorSet.playTogether(animators); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + setVisibility(INVISIBLE); + resetIconContainerPivot(); + } + + @Override + public void onAnimationCancel(Animator animation) { + super.onAnimationCancel(animation); + resetIconContainerPivot(); + } + + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + setVisibility(VISIBLE); + } + }); + + start(animatorSet); + } + + /** + * Animates this fake taskbar's appearance from the bottom of the screen. + */ + public void animateAppearanceFromBottom() { + ArrayList animators = new ArrayList<>(); + + animators.add(ObjectAnimator.ofFloat( + mBackground, View.TRANSLATION_Y, mBackground.getHeight(), 0)); + animators.add(ObjectAnimator.ofFloat(mBackground, View.ALPHA, 0f, 1f)); + animators.add(ObjectAnimator.ofFloat(mIconContainer, View.SCALE_X, 0f, 1f)); + animators.add(ObjectAnimator.ofFloat(mIconContainer, View.SCALE_Y, 0f, 1f)); + + initializeIconContainerPivot(); + + AnimatorSet animatorSet = new AnimatorSet(); + + animatorSet.playTogether(animators); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + setVisibility(VISIBLE); + } + + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + resetIconContainerPivot(); + } + + @Override + public void onAnimationCancel(Animator animation) { + super.onAnimationCancel(animation); + resetIconContainerPivot(); + } + }); + + start(animatorSet); + } + + private void initializeIconContainerPivot() { + mIconContainer.setPivotX(getWidth() / 2f); + mIconContainer.setPivotY(getHeight() * 0.8f); + } + + private void resetIconContainerPivot() { + mIconContainer.resetPivot(); + mIconContainer.setScaleX(1f); + mIconContainer.setScaleY(1f); + } + + private void start(Animator animator) { + if (mRunningAnimator != null) { + mRunningAnimator.cancel(); + } + + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationCancel(Animator animation) { + super.onAnimationCancel(animation); + mRunningAnimator = null; + } + + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + mRunningAnimator = null; + } + + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + mRunningAnimator = animator; + } + }); + + animator.start(); + } + + private Animator createIconDisappearanceToHotseatAnimator( + View taskbarIcon, View hotseatIcon, int hotseatTop) { + ArrayList animators = new ArrayList<>(); + + animators.add(ObjectAnimator.ofFloat( + taskbarIcon, + View.TRANSLATION_Y, + 0, + (hotseatTop + hotseatIcon.getTop()) - (getTop() + taskbarIcon.getTop()))); + animators.add(ObjectAnimator.ofFloat( + taskbarIcon, View.TRANSLATION_X, 0, hotseatIcon.getLeft() - taskbarIcon.getLeft())); + animators.add(ObjectAnimator.ofFloat( + taskbarIcon, + View.SCALE_X, + 1f, + (float) hotseatIcon.getWidth() / (float) taskbarIcon.getWidth())); + animators.add(ObjectAnimator.ofFloat( + taskbarIcon, + View.SCALE_Y, + 1f, + (float) hotseatIcon.getHeight() / (float) taskbarIcon.getHeight())); + animators.add(ObjectAnimator.ofFloat(taskbarIcon, View.ALPHA, 1f, 0f)); + + AnimatorSet animatorSet = new AnimatorSet(); + + animatorSet.playTogether(animators); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + super.onAnimationEnd(animation); + taskbarIcon.setVisibility(INVISIBLE); + } + + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + taskbarIcon.setVisibility(VISIBLE); + } + }); + + return animatorSet; + } + + private Animator createIconAppearanceFromHotseatAnimator( + View taskbarIcon, View hotseatIcon, int hotseatTop) { + ArrayList animators = new ArrayList<>(); + + animators.add(ObjectAnimator.ofFloat( + taskbarIcon, + View.TRANSLATION_Y, + (hotseatTop + hotseatIcon.getTop()) - (getTop() + taskbarIcon.getTop()), + 0)); + animators.add(ObjectAnimator.ofFloat( + taskbarIcon, View.TRANSLATION_X, hotseatIcon.getLeft() - taskbarIcon.getLeft(), 0)); + animators.add(ObjectAnimator.ofFloat( + taskbarIcon, + View.SCALE_X, + (float) hotseatIcon.getWidth() / (float) taskbarIcon.getWidth(), + 1f)); + animators.add(ObjectAnimator.ofFloat( + taskbarIcon, + View.SCALE_Y, + (float) hotseatIcon.getHeight() / (float) taskbarIcon.getHeight(), + 1f)); + animators.add(ObjectAnimator.ofFloat(taskbarIcon, View.ALPHA, 0f, 1f)); + + AnimatorSet animatorSet = new AnimatorSet(); + + animatorSet.playTogether(animators); + animatorSet.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + super.onAnimationStart(animation); + taskbarIcon.setVisibility(VISIBLE); + } + }); + + return animatorSet; + } +} diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java index a45f27383b..bbb22e643f 100644 --- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java @@ -95,8 +95,10 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll showFeedback(R.string.home_gesture_feedback_swipe_too_far_from_edge); break; case OVERVIEW_GESTURE_COMPLETED: - fadeOutFakeTaskView(true, true, () -> - showFeedback(R.string.home_gesture_feedback_overview_detected)); + fadeOutFakeTaskView(true, true, () -> { + showFeedback(R.string.home_gesture_feedback_overview_detected); + showFakeTaskbar(/* animateFromHotseat= */ false); + }); break; case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION: case HOME_OR_OVERVIEW_CANCELLED: diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java index dcae07d88d..423e66f07d 100644 --- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java @@ -61,7 +61,7 @@ public class HomeGestureTutorialFragment extends TutorialFragment { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); - controller.resetFakeTaskView(); + controller.resetFakeTaskView(true); } }); ArrayList animators = new ArrayList<>(); @@ -76,7 +76,7 @@ public class HomeGestureTutorialFragment extends TutorialFragment { @Override public void onAnimationCancel(Animator animation) { super.onAnimationCancel(animation); - controller.resetFakeTaskView(); + controller.resetFakeTaskView(true); } }); finalAnimation.playSequentially(animators); diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java index 24ef1fab4d..0fea0d7fe2 100644 --- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java @@ -93,8 +93,8 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont switch (result) { case HOME_GESTURE_COMPLETED: { animateFakeTaskViewHome(finalVelocity, () -> { - resetFakeTaskView(); showFeedback(R.string.overview_gesture_feedback_home_detected); + resetFakeTaskView(true); }); break; } @@ -146,6 +146,7 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont AnimatorSet animset = new AnimatorSet(); animset.playTogether(animators); + hideFakeTaskbar(/* animateToHotseat= */ false); animset.start(); mRunningWindowAnim = SwipeUpAnimationLogic.RunningWindowAnim.wrap(animset); } diff --git a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java index 57a76ca041..f63a9459a9 100644 --- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java @@ -72,7 +72,7 @@ public class OverviewGestureTutorialFragment extends TutorialFragment { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); - controller.resetFakeTaskView(); + controller.resetFakeTaskView(false); } }); ArrayList animators = new ArrayList<>(); @@ -88,7 +88,7 @@ public class OverviewGestureTutorialFragment extends TutorialFragment { @Override public void onAnimationCancel(Animator animation) { super.onAnimationCancel(animation); - controller.resetFakeTaskView(); + controller.resetFakeTaskView(false); } }); finalAnimation.playSequentially(animators); diff --git a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java index a923519a75..68df208360 100644 --- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java @@ -198,11 +198,12 @@ abstract class SwipeUpGestureTutorialController extends TutorialController { } } AnimatorSet animset = anim.buildAnim(); + hideFakeTaskbar(/* animateToHotseat= */ false); animset.start(); mRunningWindowAnim = RunningWindowAnim.wrap(animset); } - void resetFakeTaskView() { + void resetFakeTaskView(boolean animateFromHome) { mFakeTaskView.setVisibility(View.VISIBLE); PendingAnimation anim = new PendingAnimation(300); anim.setFloat(mTaskViewSwipeUpAnimation @@ -210,12 +211,14 @@ abstract class SwipeUpGestureTutorialController extends TutorialController { anim.setViewAlpha(mFakeTaskView, 1, ACCEL); anim.addListener(mResetTaskView); AnimatorSet animset = anim.buildAnim(); + showFakeTaskbar(animateFromHome); animset.start(); mRunningWindowAnim = RunningWindowAnim.wrap(animset); } void animateFakeTaskViewHome(PointF finalVelocity, @Nullable Runnable onEndRunnable) { cancelRunningAnimation(); + hideFakeTaskbar(/* animateToHotseat= */ true); mFakePreviousTaskView.setVisibility(View.INVISIBLE); mFakeHotseatView.setVisibility(View.VISIBLE); mShowPreviousTasks = false; diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java index 9c1ff4dbd3..a59b0d76be 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java @@ -89,6 +89,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, @Nullable View mHotseatIconView; final ClipIconView mFakeIconView; final FrameLayout mFakeTaskView; + final AnimatedTaskbarView mFakeTaskbarView; final AnimatedTaskView mFakePreviousTaskView; final View mRippleView; final RippleDrawable mRippleDrawable; @@ -104,6 +105,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, private final Runnable mTitleViewCallback; @Nullable private Runnable mFeedbackViewCallback; @Nullable private Runnable mFakeTaskViewCallback; + @Nullable private Runnable mFakeTaskbarViewCallback; private final Runnable mShowFeedbackRunnable; TutorialController(TutorialFragment tutorialFragment, TutorialType tutorialType) { @@ -122,6 +124,7 @@ abstract class TutorialController implements BackGestureAttemptCallback, mFakeHotseatView = rootView.findViewById(R.id.gesture_tutorial_fake_hotseat_view); mFakeIconView = rootView.findViewById(R.id.gesture_tutorial_fake_icon_view); mFakeTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_task_view); + mFakeTaskbarView = rootView.findViewById(R.id.gesture_tutorial_fake_taskbar_view); mFakePreviousTaskView = rootView.findViewById(R.id.gesture_tutorial_fake_previous_task_view); mRippleView = rootView.findViewById(R.id.gesture_tutorial_ripple_view); @@ -319,6 +322,10 @@ abstract class TutorialController implements BackGestureAttemptCallback, mFakeTaskView.removeCallbacks(mFakeTaskViewCallback); mFakeTaskViewCallback = null; } + if (mFakeTaskbarViewCallback != null) { + mFakeTaskbarView.removeCallbacks(mFakeTaskbarViewCallback); + mFakeTaskbarViewCallback = null; + } mFeedbackTitleView.removeCallbacks(mTitleViewCallback); } @@ -429,6 +436,38 @@ abstract class TutorialController implements BackGestureAttemptCallback, mActionButton.setOnClickListener(this::onActionButtonClicked); } + void hideFakeTaskbar(boolean animateToHotseat) { + if (!mTutorialFragment.isLargeScreen()) { + return; + } + if (mFakeTaskbarViewCallback != null) { + mFakeTaskbarView.removeCallbacks(mFakeTaskbarViewCallback); + } + if (animateToHotseat) { + mFakeTaskbarViewCallback = () -> + mFakeTaskbarView.animateDisappearanceToHotseat(mFakeHotseatView); + } else { + mFakeTaskbarViewCallback = mFakeTaskbarView::animateDisappearanceToBottom; + } + mFakeTaskbarView.post(mFakeTaskbarViewCallback); + } + + void showFakeTaskbar(boolean animateFromHotseat) { + if (!mTutorialFragment.isLargeScreen()) { + return; + } + if (mFakeTaskbarViewCallback != null) { + mFakeTaskbarView.removeCallbacks(mFakeTaskbarViewCallback); + } + if (animateFromHotseat) { + mFakeTaskbarViewCallback = () -> + mFakeTaskbarView.animateAppearanceFromHotseat(mFakeHotseatView); + } else { + mFakeTaskbarViewCallback = mFakeTaskbarView::animateAppearanceFromBottom; + } + mFakeTaskbarView.post(mFakeTaskbarViewCallback); + } + void updateFakeAppTaskViewLayout(@LayoutRes int mockAppTaskLayoutResId) { updateFakeViewLayout(mFakeTaskView, mockAppTaskLayoutResId); } @@ -480,6 +519,8 @@ abstract class TutorialController implements BackGestureAttemptCallback, mTutorialFragment.isLargeScreen() ? R.dimen.gesture_tutorial_foldable_feedback_margin_start_end : R.dimen.gesture_tutorial_feedback_margin_start_end)); + + mFakeTaskbarView.setVisibility(mTutorialFragment.isLargeScreen() ? View.VISIBLE : GONE); } }