Files
Lawnchair/quickstep/src/com/android/quickstep/interaction/OverviewGestureTutorialController.java
T
Saumya Prakash 5c5472ff96 Fix UI issues of fake task view in gesture nav tutorial.
This change fixes the bug where the view for the fake task in the overview gesture was not being reset correctly. This was leading to UI issues such as lack of rounded corners and incorrect animations in the gesture navigation tutorial.

Flag: ENABLE_NEW_GESTURE_NAV_TUTORIAL
Fix: 281121451
Fix: 281121699
Fix: 281785378
Test: Manually went through the tutorial on handheld, foldable, and
tablet devices

Change-Id: I424a471013d2b8667724f790618d142ba7ae9a7b
2023-05-11 17:41:18 +00:00

228 lines
9.2 KiB
Java

/*
* Copyright (C) 2020 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 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;
import com.android.launcher3.anim.PendingAnimation;
import com.android.quickstep.SwipeUpAnimationLogic;
import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult;
import com.android.quickstep.interaction.NavBarGestureHandler.NavBarGestureResult;
import java.util.ArrayList;
/** A {@link TutorialController} for the Overview tutorial. */
@TargetApi(Build.VERSION_CODES.R)
final class OverviewGestureTutorialController extends SwipeUpGestureTutorialController {
OverviewGestureTutorialController(OverviewGestureTutorialFragment fragment,
TutorialType tutorialType) {
super(fragment, tutorialType);
}
@Override
public int getIntroductionTitle() {
return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.string.overview_gesture_tutorial_title
: R.string.overview_gesture_intro_title;
}
@Override
public int getIntroductionSubtitle() {
return R.string.overview_gesture_intro_subtitle;
}
@Override
public int getSpokenIntroductionSubtitle() {
return R.string.overview_gesture_spoken_intro_subtitle;
}
@Override
public int getSuccessFeedbackSubtitle() {
return mTutorialFragment.getNumSteps() > 1 && mTutorialFragment.isAtFinalStep()
? R.string.overview_gesture_feedback_complete_with_follow_up
: R.string.overview_gesture_feedback_complete_without_follow_up;
}
@Override
protected int getMockAppTaskLayoutResId() {
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() {
return mTutorialFragment.isLargeScreen()
? mTutorialFragment.isFoldable()
? R.raw.overview_gesture_tutorial_open_foldable_animation
: R.raw.overview_gesture_tutorial_tablet_animation
: R.raw.overview_gesture_tutorial_animation;
}
@Override
protected int getSwipeActionColorResId() {
return R.color.gesture_overview_background;
}
@Override
protected int getMockPreviousAppTaskThumbnailColorResId() {
return ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()
? R.color.gesture_overview_tutorial_swipe_rect
: R.color.gesture_tutorial_fake_previous_task_view_color;
}
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
case OVERVIEW_NAVIGATION:
switch (result) {
case BACK_COMPLETED_FROM_LEFT:
case BACK_COMPLETED_FROM_RIGHT:
case BACK_CANCELLED_FROM_LEFT:
case BACK_CANCELLED_FROM_RIGHT:
case BACK_NOT_STARTED_TOO_FAR_FROM_EDGE:
resetTaskView();
showFeedback(R.string.overview_gesture_feedback_swipe_too_far_from_edge);
break;
}
break;
case OVERVIEW_NAVIGATION_COMPLETE:
if (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT
|| result == BackGestureResult.BACK_COMPLETED_FROM_RIGHT) {
mTutorialFragment.close();
}
break;
}
}
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
case OVERVIEW_NAVIGATION:
switch (result) {
case HOME_GESTURE_COMPLETED: {
animateFakeTaskViewHome(finalVelocity, () -> {
showFeedback(R.string.overview_gesture_feedback_home_detected);
resetFakeTaskView(true);
});
break;
}
case HOME_NOT_STARTED_TOO_FAR_FROM_EDGE:
case OVERVIEW_NOT_STARTED_TOO_FAR_FROM_EDGE:
resetTaskView();
showFeedback(R.string.overview_gesture_feedback_swipe_too_far_from_edge);
break;
case OVERVIEW_GESTURE_COMPLETED:
mTutorialFragment.releaseFeedbackAnimation();
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:
fadeOutFakeTaskView(false, true, null);
showFeedback(R.string.overview_gesture_feedback_wrong_swipe_direction);
break;
}
break;
case OVERVIEW_NAVIGATION_COMPLETE:
if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) {
mTutorialFragment.close();
}
break;
}
}
/**
* 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()) {
Animator multiRowAnimation = mFakePreviousTaskView.createAnimationToMultiRowLayout();
if (multiRowAnimation != null) {
multiRowAnimation.setDuration(TASK_VIEW_END_ANIMATION_DURATION_MILLIS);
animators.add(multiRowAnimation);
}
}
animators.add(anim.buildAnim());
AnimatorSet animset = new AnimatorSet();
animset.playTogether(animators);
animset.start();
mRunningWindowAnim = SwipeUpAnimationLogic.RunningWindowAnim.wrap(animset);
}
}