Merge "Add mock animated taskbar to gesture nav tutorial for foldable devices." into sc-v2-dev
diff --git a/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml b/quickstep/res/layout/gesture_tutorial_foldable_mock_conversation.xml
index 34bd4e2..b0cc00b 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 0309cc3..e5cd9bc 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 0000000..ddfeeec
--- /dev/null
+++ b/quickstep/res/layout/gesture_tutorial_foldable_mock_taskbar.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="utf-8"?>
+<com.android.quickstep.interaction.AnimatedTaskbarView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/gesture_tutorial_mock_taskbar_height">
+
+ <View
+ android:id="@+id/taskbar_background"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@color/gesture_tutorial_taskbar_color"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/icon_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toEndOf="parent">
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/taskbar_icon_1"
+ android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+ android:layout_marginStart="@dimen/gesture_tutorial_taskbar_padding_start_end"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_1"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintHorizontal_chainStyle="spread_inside"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintEnd_toStartOf="@id/taskbar_icon_2"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/taskbar_icon_2"
+ android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_2"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/taskbar_icon_1"
+ app:layout_constraintEnd_toStartOf="@id/taskbar_icon_3"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/taskbar_icon_3"
+ android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_3"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/taskbar_icon_2"
+ app:layout_constraintEnd_toStartOf="@id/taskbar_icon_4"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/taskbar_icon_4"
+ android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_1"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/taskbar_icon_3"
+ app:layout_constraintEnd_toStartOf="@id/taskbar_icon_5"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/taskbar_icon_5"
+ android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_4"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/taskbar_icon_4"
+ app:layout_constraintEnd_toStartOf="@id/taskbar_icon_6"/>
+
+ <androidx.cardview.widget.CardView
+ android:id="@+id/taskbar_icon_6"
+ android:layout_width="@dimen/gesture_tutorial_taskbar_icon_size"
+ android:layout_height="@dimen/gesture_tutorial_taskbar_icon_size"
+ android:layout_marginEnd="@dimen/gesture_tutorial_taskbar_padding_start_end"
+
+ app:cardElevation="0dp"
+ app:cardCornerRadius="@dimen/gesture_tutorial_taskbar_icon_corner_radius"
+ app:cardBackgroundColor="@color/mock_app_icon_2"
+ app:layout_constraintDimensionRatio="1:1"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toEndOf="@id/taskbar_icon_5"
+ app:layout_constraintEnd_toEndOf="parent"/>
+
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+</com.android.quickstep.interaction.AnimatedTaskbarView>
\ 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 41d0a1d..08e6178 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"/>
+ <include
+ layout="@layout/gesture_tutorial_foldable_mock_taskbar"
+ android:id="@+id/gesture_tutorial_fake_taskbar_view"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/gesture_tutorial_mock_taskbar_height"
+ android:layout_alignParentBottom="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentEnd="true" />
+
<ImageView
android:id="@+id/gesture_tutorial_edge_gesture_video"
android:layout_width="match_parent"
diff --git a/quickstep/res/values/colors.xml b/quickstep/res/values/colors.xml
index 1bddb57..fb2ee1c 100644
--- a/quickstep/res/values/colors.xml
+++ b/quickstep/res/values/colors.xml
@@ -40,6 +40,7 @@
<color name="gesture_tutorial_fake_previous_task_view_color">#3C4043</color> <!-- Gray -->
<color name="gesture_tutorial_action_button_label_color">#FF000000</color>
<color name="gesture_tutorial_primary_color">#B7F29F</color> <!-- Light Green -->
+ <color name="gesture_tutorial_taskbar_color">#202124</color>
<!-- Mock hotseat -->
<color name="mock_app_icon_1">#8AB4F8</color>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index fa21b0a..4ebf5cf 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -121,6 +121,7 @@
<dimen name="gesture_tutorial_foldable_feedback_margin_start_end">140dp</dimen>
<dimen name="gesture_tutorial_multi_row_task_view_spacing">72dp</dimen>
<dimen name="gesture_tutorial_small_task_view_corner_radius">18dp</dimen>
+ <dimen name="gesture_tutorial_mock_taskbar_height">80dp</dimen>
<!-- Gesture Tutorial mock conversations -->
<dimen name="gesture_tutorial_message_icon_size">44dp</dimen>
@@ -155,6 +156,11 @@
<dimen name="gesture_tutorial_webpage_large_line_height">36dp</dimen>
<dimen name="gesture_tutorial_webpage_small_line_height">22dp</dimen>
+ <!-- Gesture Tutorial mock taskbar -->
+ <dimen name="gesture_tutorial_taskbar_icon_size">44dp</dimen>
+ <dimen name="gesture_tutorial_taskbar_icon_corner_radius">100dp</dimen>
+ <dimen name="gesture_tutorial_taskbar_padding_start_end">218dp</dimen>
+
<!-- All Set page -->
<dimen name="allset_page_margin_horizontal">40dp</dimen>
<dimen name="allset_title_margin_top">24dp</dimen>
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 0000000..e8cc45b
--- /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<Animator> 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<Animator> 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<Animator> 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<Animator> 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<Animator> 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<Animator> 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 a45f273..bbb22e6 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java
@@ -95,8 +95,10 @@
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 dcae07d..423e66f 100644
--- a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java
@@ -61,7 +61,7 @@
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- controller.resetFakeTaskView();
+ controller.resetFakeTaskView(true);
}
});
ArrayList<Animator> animators = new ArrayList<>();
@@ -76,7 +76,7 @@
@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 24ef1fa..0fea0d7 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
@@ -93,8 +93,8 @@
switch (result) {
case HOME_GESTURE_COMPLETED: {
animateFakeTaskViewHome(finalVelocity, () -> {
- resetFakeTaskView();
showFeedback(R.string.overview_gesture_feedback_home_detected);
+ resetFakeTaskView(true);
});
break;
}
@@ -146,6 +146,7 @@
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 57a76ca..f63a945 100644
--- a/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
+++ b/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialFragment.java
@@ -72,7 +72,7 @@
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- controller.resetFakeTaskView();
+ controller.resetFakeTaskView(false);
}
});
ArrayList<Animator> animators = new ArrayList<>();
@@ -88,7 +88,7 @@
@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 a923519..68df208 100644
--- a/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/SwipeUpGestureTutorialController.java
@@ -198,11 +198,12 @@
}
}
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 @@
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 9c1ff4d..a59b0d7 100644
--- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java
+++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java
@@ -89,6 +89,7 @@
@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 @@
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 @@
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 @@
mFakeTaskView.removeCallbacks(mFakeTaskViewCallback);
mFakeTaskViewCallback = null;
}
+ if (mFakeTaskbarViewCallback != null) {
+ mFakeTaskbarView.removeCallbacks(mFakeTaskbarViewCallback);
+ mFakeTaskbarViewCallback = null;
+ }
mFeedbackTitleView.removeCallbacks(mTitleViewCallback);
}
@@ -429,6 +436,38 @@
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 @@
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);
}
}