resolve merge conflicts of 694b667138 to sc-dev-plus-aosp

Test: manual
Bug: none

Change-Id: I2264c2dd3e0152186b7b14f76fa52126cbefe984
This commit is contained in:
Schneider Victor-tulias
2021-05-27 16:52:29 -07:00
8 changed files with 142 additions and 118 deletions

View File

@@ -95,16 +95,14 @@
<string name="back_gesture_feedback_swipe_too_far_from_left_edge">Make sure you swipe from the far-left edge.</string>
<!-- Feedback shown during interactive parts of Back gesture tutorial for left edge when the gesture is cancelled. [CHAR LIMIT=100] -->
<string name="back_gesture_feedback_cancelled_left_edge">Make sure you swipe from the left edge to the middle of the screen and let go.</string>
<!-- Feedback title shown after completing the left back gesture before continuing on to the right edge. [CHAR LIMIT=60] -->
<string name="back_gesture_feedback_title_complete_left_edge">Nice! Now swipe from the right to go back</string>
<!-- Feedback subtitle shown after completing the left back gesture before continuing on to the right edge. [CHAR LIMIT=200] -->
<string name="back_gesture_feedback_subtitle_complete_left_edge">You can also go back to the last screen by swiping from the right edge to the middle of the screen.</string>
<!-- Feedback shown during interactive parts of Back gesture tutorial for right edge when the gesture is too far from the edge. [CHAR LIMIT=100] -->
<string name="back_gesture_feedback_swipe_too_far_from_right_edge">Make sure you swipe from the far-right edge.</string>
<!-- Feedback shown during interactive parts of Back gesture tutorial for right edge when the gesture is cancelled. [CHAR LIMIT=100] -->
<string name="back_gesture_feedback_cancelled_right_edge">Make sure you swipe from the right edge to the middle of the screen and let go.</string>
<!-- Feedback shown after completing the back gesture step if the user is following the full gesture tutorial flow. [CHAR LIMIT=100] -->
<string name="back_gesture_feedback_complete_with_follow_up">You completed the go back gesture. Next up, learn how to switch apps.</string>
<string name="back_gesture_feedback_complete_with_back_right_follow_up">You learned how to swipe from the left to go back.</string>
<!-- Feedback shown after completing the back gesture step if the user is following the full gesture tutorial flow. [CHAR LIMIT=100] -->
<string name="back_gesture_feedback_complete_with_overview_follow_up">You learned how to swipe from the right to go back. Next up, learn how to switch apps.</string>
<!-- Feedback shown after completing the back gesture step if the user started this tutorial individually. [CHAR LIMIT=100] -->
<string name="back_gesture_feedback_complete_without_follow_up">You completed the go back gesture.</string>
<!-- Feedback shown during interactive parts of Back gesture tutorial when the gesture is within the nav bar region. [CHAR LIMIT=100] -->
@@ -112,10 +110,14 @@
<!-- Subtitle shown on the confirmation screen after successful gesture. [CHAR LIMIT=60] -->
<string name="back_gesture_tutorial_confirm_subtitle">To change the sensitivity of the back gesture, go to Settings</string>
<!-- Feedback shown during interactive parts of Home gesture tutorial when the gesture is started too far from the edge. [CHAR LIMIT=100] -->
<!-- Introduction title for the Back gesture tutorial. [CHAR LIMIT=100] -->
<string name="back_gesture_intro_title">Swipe from the left to go back</string>
<!-- Introduction subtitle for the Back gesture tutorial. [CHAR LIMIT=100] -->
<string name="back_gesture_intro_subtitle">To go back to the last screen you were on, swipe from the left edge to the middle of the screen.</string>
<!-- Introduction title for the left edge Back gesture tutorial. [CHAR LIMIT=100] -->
<string name="back_left_gesture_intro_title">Swipe from the left to go back</string>
<!-- Introduction title for the right edge Back gesture tutorial. [CHAR LIMIT=100] -->
<string name="back_right_gesture_intro_title">Swipe from the right to go back</string>
<!-- Introduction subtitle for the Back left gesture tutorial. [CHAR LIMIT=200] -->
<string name="back_left_gesture_intro_subtitle">To go back to the last screen you were on, swipe from the left edge to the middle of the screen.</string>
<!-- Introduction subtitle for the Back right gesture tutorial. [CHAR LIMIT=100] -->
<string name="back_right_gesture_intro_subtitle">You can also go back to the last screen by swiping from the right edge to the middle of the screen. Try it now.</string>
<string name="home_gesture_feedback_swipe_too_far_from_edge">Make sure you swipe up from the bottom edge of the screen.</string>
<!-- Feedback shown during interactive parts of Home gesture tutorial when the Overview gesture is detected. [CHAR LIMIT=100] -->

View File

@@ -37,13 +37,14 @@ final class BackGestureTutorialController extends TutorialController {
@Override
public Integer getIntroductionTitle() {
return mTutorialType == LEFT_EDGE_BACK_NAVIGATION
? R.string.back_gesture_intro_title : null;
? R.string.back_left_gesture_intro_title : R.string.back_right_gesture_intro_title;
}
@Override
public Integer getIntroductionSubtitle() {
return mTutorialType == LEFT_EDGE_BACK_NAVIGATION
? R.string.back_gesture_intro_subtitle : null;
? R.string.back_left_gesture_intro_subtitle
: R.string.back_right_gesture_intro_subtitle;
}
@Override
@@ -53,6 +54,9 @@ final class BackGestureTutorialController extends TutorialController {
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (mGestureCompleted) {
return;
}
switch (mTutorialType) {
case RIGHT_EDGE_BACK_NAVIGATION:
handleAttemptFromRight(result);
@@ -76,9 +80,9 @@ final class BackGestureTutorialController extends TutorialController {
hideFeedback(true);
mFakeTaskView.setBackground(AppCompatResources.getDrawable(mContext,
R.drawable.mock_conversations_list));
int subtitleResId = mTutorialFragment.getNumSteps() == 1
int subtitleResId = mTutorialFragment.isAtFinalStep()
? R.string.back_gesture_feedback_complete_without_follow_up
: R.string.back_gesture_feedback_complete_with_follow_up;
: R.string.back_gesture_feedback_complete_with_overview_follow_up;
showFeedback(subtitleResId, true);
break;
case BACK_CANCELLED_FROM_RIGHT:
@@ -102,10 +106,10 @@ final class BackGestureTutorialController extends TutorialController {
hideFeedback(true);
mFakeTaskView.setBackground(AppCompatResources.getDrawable(mContext,
R.drawable.mock_conversations_list));
showFeedback(
R.string.back_gesture_feedback_title_complete_left_edge,
R.string.back_gesture_feedback_subtitle_complete_left_edge,
() -> mTutorialFragment.changeController(RIGHT_EDGE_BACK_NAVIGATION));
int subtitleResId = mTutorialFragment.isAtFinalStep()
? R.string.back_gesture_feedback_complete_without_follow_up
: R.string.back_gesture_feedback_complete_with_back_right_follow_up;
showFeedback(subtitleResId, true);
break;
case BACK_CANCELLED_FROM_LEFT:
showFeedback(R.string.back_gesture_feedback_cancelled_left_edge);
@@ -123,6 +127,9 @@ final class BackGestureTutorialController extends TutorialController {
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
if (mGestureCompleted) {
return;
}
if (mTutorialType == BACK_NAVIGATION_COMPLETE) {
if (result == NavBarGestureResult.HOME_GESTURE_COMPLETED) {
mTutorialFragment.closeTutorial();

View File

@@ -48,6 +48,9 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (mGestureCompleted) {
return;
}
switch (mTutorialType) {
case HOME_NAVIGATION:
switch (result) {
@@ -70,7 +73,7 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
if (mHideFeedbackEndAction != null) {
if (mGestureCompleted) {
return;
}
switch (mTutorialType) {
@@ -80,7 +83,7 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
mTutorialFragment.releaseGestureVideoView();
animateFakeTaskViewHome(finalVelocity, null);
showActionButton();
int subtitleResId = mTutorialFragment.getNumSteps() == 1
int subtitleResId = mTutorialFragment.isAtFinalStep()
? R.string.home_gesture_feedback_complete_without_follow_up
: R.string.home_gesture_feedback_complete_with_follow_up;
showFeedback(subtitleResId, true);

View File

@@ -55,6 +55,9 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (mGestureCompleted) {
return;
}
switch (mTutorialType) {
case OVERVIEW_NAVIGATION:
switch (result) {
@@ -77,7 +80,7 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
if (mHideFeedbackEndAction != null) {
if (mGestureCompleted) {
return;
}
switch (mTutorialType) {
@@ -103,9 +106,10 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
animset.start();
mRunningWindowAnim = SwipeUpAnimationLogic.RunningWindowAnim.wrap(animset);
onMotionPaused(true /*arbitrary value*/);
int subtitleResId = mTutorialFragment.getNumSteps() == 1
? R.string.overview_gesture_feedback_complete_without_follow_up
: R.string.overview_gesture_feedback_complete_with_follow_up;
int subtitleResId = mTutorialFragment.getNumSteps() > 1
&& mTutorialFragment.isAtFinalStep()
? R.string.overview_gesture_feedback_complete_with_follow_up
: R.string.overview_gesture_feedback_complete_without_follow_up;
showFeedback(subtitleResId, true);
break;
case HOME_OR_OVERVIEW_NOT_STARTED_WRONG_SWIPE_DIRECTION:

View File

@@ -214,7 +214,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
@Override
public void setNavBarGestureProgress(@Nullable Float displacement) {
if (mHideFeedbackEndAction != null) {
if (mGestureCompleted) {
return;
}
if (displacement != null) {
@@ -238,7 +238,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
@Override
public void onMotionPaused(boolean unused) {
if (mHideFeedbackEndAction != null) {
if (mGestureCompleted) {
return;
}
if (mShowTasks) {

View File

@@ -27,12 +27,14 @@ import android.graphics.drawable.RippleDrawable;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.CallSuper;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.AlertDialog;
@@ -53,7 +55,6 @@ abstract class TutorialController implements BackGestureAttemptCallback,
private static final String PIXEL_TIPS_APP_PACKAGE_NAME = "com.google.android.apps.tips";
private static final CharSequence DEFAULT_PIXEL_TIPS_APP_NAME = "Pixel Tips";
private static final int FEEDBACK_VISIBLE_MS = 5000;
private static final int FEEDBACK_ANIMATION_MS = 250;
private static final int RIPPLE_VISIBLE_MS = 300;
@@ -73,10 +74,10 @@ abstract class TutorialController implements BackGestureAttemptCallback,
final RippleDrawable mRippleDrawable;
final Button mActionButton;
final TutorialStepIndicator mTutorialStepView;
private final Runnable mHideFeedbackRunnable;
Runnable mHideFeedbackEndAction;
private final AlertDialog mSkipTutorialDialog;
protected boolean mGestureCompleted = false;
TutorialController(TutorialFragment tutorialFragment, TutorialType tutorialType) {
mTutorialFragment = tutorialFragment;
mTutorialType = tutorialType;
@@ -99,12 +100,6 @@ abstract class TutorialController implements BackGestureAttemptCallback,
mTutorialStepView =
rootView.findViewById(R.id.gesture_tutorial_fragment_feedback_tutorial_step);
mSkipTutorialDialog = createSkipTutorialDialog();
mHideFeedbackRunnable =
() -> mFeedbackView.animate()
.translationY(-mFeedbackView.getTop() - mFeedbackView.getHeight())
.setDuration(FEEDBACK_ANIMATION_MS)
.withEndAction(this::hideFeedbackEndAction).start();
}
private void showSkipTutorialDialog() {
@@ -156,6 +151,25 @@ abstract class TutorialController implements BackGestureAttemptCallback,
return null;
}
void showFeedback() {
if (mGestureCompleted) {
mFeedbackView.setTranslationY(0);
return;
}
AnimatedVectorDrawable tutorialAnimation = mTutorialFragment.getTutorialAnimation();
AnimatedVectorDrawable gestureAnimation = mTutorialFragment.getGestureAnimation();
if (tutorialAnimation != null && gestureAnimation != null) {
TextView title = mFeedbackView.findViewById(
R.id.gesture_tutorial_fragment_feedback_title);
playFeedbackVideo(tutorialAnimation, gestureAnimation, () -> {
mFeedbackView.setTranslationY(0);
title.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
});
}
}
/**
* Show feedback reflecting a failed gesture attempt.
*
@@ -165,98 +179,50 @@ abstract class TutorialController implements BackGestureAttemptCallback,
showFeedback(subtitleResId, false);
}
/**
* Show feedback reflecting a failed gesture attempt.
*
* @param showActionButton Whether the tutorial feedback's action button should be shown.
**/
void showFeedback(int subtitleResId, boolean showActionButton) {
showFeedback(subtitleResId, showActionButton ? () -> {} : null, showActionButton);
}
/**
* Show feedback reflecting a failed gesture attempt.
**/
void showFeedback(int titleResId, int subtitleResId, @Nullable Runnable successEndAction) {
showFeedback(titleResId, subtitleResId, successEndAction, false);
}
/**
* Show feedback reflecting the result of a gesture attempt.
*
* @param successEndAction Non-null iff the gesture was successful; this is run after the
* feedback is shown (i.e. to go to the next step)
* @param isGestureSuccessful Whether the tutorial feedback's action button should be shown.
**/
void showFeedback(
int subtitleResId, @Nullable Runnable successEndAction, boolean showActionButton) {
void showFeedback(int subtitleResId, boolean isGestureSuccessful) {
showFeedback(
successEndAction == null
? R.string.gesture_tutorial_try_again
: R.string.gesture_tutorial_nice,
isGestureSuccessful
? R.string.gesture_tutorial_nice : R.string.gesture_tutorial_try_again,
subtitleResId,
successEndAction,
showActionButton);
isGestureSuccessful);
}
void showFeedback(
int titleResId,
int subtitleResId,
@Nullable Runnable successEndAction,
boolean showActionButton) {
if (mHideFeedbackEndAction != null) {
return;
}
boolean isGestureSuccessful) {
TextView title = mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_title);
title.setText(titleResId);
TextView subtitle =
mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_subtitle);
subtitle.setText(subtitleResId);
if (showActionButton) {
if (isGestureSuccessful) {
showActionButton();
}
mHideFeedbackEndAction = successEndAction;
mGestureCompleted = isGestureSuccessful;
AnimatedVectorDrawable tutorialAnimation = mTutorialFragment.getTutorialAnimation();
AnimatedVectorDrawable gestureAnimation = mTutorialFragment.getGestureAnimation();
if (tutorialAnimation != null && gestureAnimation != null) {
if (successEndAction == null) {
if (tutorialAnimation.isRunning()) {
tutorialAnimation.reset();
}
tutorialAnimation.registerAnimationCallback(new Animatable2.AnimationCallback() {
@Override
public void onAnimationStart(Drawable drawable) {
super.onAnimationStart(drawable);
mGestureVideoView.setVisibility(GONE);
if (gestureAnimation.isRunning()) {
gestureAnimation.stop();
}
mFeedbackView.setTranslationY(
-mFeedbackView.getHeight() - mFeedbackView.getTop());
mFeedbackView.setVisibility(View.VISIBLE);
mFeedbackView.animate()
.setDuration(FEEDBACK_ANIMATION_MS)
.translationY(0)
.start();
mFeedbackView.removeCallbacks(mHideFeedbackRunnable);
mFeedbackView.postDelayed(mHideFeedbackRunnable, FEEDBACK_VISIBLE_MS);
}
@Override
public void onAnimationEnd(Drawable drawable) {
super.onAnimationEnd(drawable);
mGestureVideoView.setVisibility(View.VISIBLE);
gestureAnimation.start();
tutorialAnimation.unregisterAnimationCallback(this);
}
if (!isGestureSuccessful) {
playFeedbackVideo(tutorialAnimation, gestureAnimation, () -> {
mFeedbackView.setTranslationY(
-mFeedbackView.getHeight() - mFeedbackView.getTop());
mFeedbackView.setVisibility(View.VISIBLE);
mFeedbackView.animate()
.setDuration(FEEDBACK_ANIMATION_MS)
.translationY(0)
.start();
title.postDelayed(
() -> title.sendAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_FOCUSED),
FEEDBACK_ANIMATION_MS);
});
tutorialAnimation.start();
mFeedbackVideoView.setVisibility(View.VISIBLE);
return;
} else {
mTutorialFragment.releaseFeedbackVideoView();
@@ -268,15 +234,13 @@ abstract class TutorialController implements BackGestureAttemptCallback,
.setDuration(FEEDBACK_ANIMATION_MS)
.translationY(0)
.start();
mFeedbackView.removeCallbacks(mHideFeedbackRunnable);
if (!showActionButton) {
mFeedbackView.postDelayed(mHideFeedbackRunnable, FEEDBACK_VISIBLE_MS);
}
title.postDelayed(
() -> title.sendAccessibilityEvent(
AccessibilityEvent.TYPE_VIEW_FOCUSED),
FEEDBACK_ANIMATION_MS);
}
void hideFeedback(boolean releaseFeedbackVideo) {
mFeedbackView.removeCallbacks(mHideFeedbackRunnable);
mHideFeedbackEndAction = null;
mFeedbackView.clearAnimation();
mFeedbackView.setVisibility(View.INVISIBLE);
if (releaseFeedbackVideo) {
@@ -284,11 +248,41 @@ abstract class TutorialController implements BackGestureAttemptCallback,
}
}
void hideFeedbackEndAction() {
if (mHideFeedbackEndAction != null) {
mHideFeedbackEndAction.run();
mHideFeedbackEndAction = null;
private void playFeedbackVideo(
@NonNull AnimatedVectorDrawable tutorialAnimation,
@NonNull AnimatedVectorDrawable gestureAnimation,
@NonNull Runnable onStartRunnable) {
if (tutorialAnimation.isRunning()) {
tutorialAnimation.reset();
}
tutorialAnimation.registerAnimationCallback(new Animatable2.AnimationCallback() {
@Override
public void onAnimationStart(Drawable drawable) {
super.onAnimationStart(drawable);
mGestureVideoView.setVisibility(GONE);
if (gestureAnimation.isRunning()) {
gestureAnimation.stop();
}
onStartRunnable.run();
}
@Override
public void onAnimationEnd(Drawable drawable) {
super.onAnimationEnd(drawable);
mGestureVideoView.setVisibility(View.VISIBLE);
gestureAnimation.start();
tutorialAnimation.unregisterAnimationCallback(this);
}
});
tutorialAnimation.start();
mFeedbackVideoView.setVisibility(View.VISIBLE);
}
void setRippleHotspot(float x, float y) {
@@ -317,6 +311,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
updateSubtext();
updateDrawables();
mGestureCompleted = false;
if (mFakeLauncherView != null) {
mFakeLauncherView.setVisibility(View.INVISIBLE);
}

View File

@@ -57,6 +57,8 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
@Nullable private AnimatedVectorDrawable mGestureAnimation = null;
private boolean mIntroductionShown = false;
private boolean mFragmentStopped = false;
public static TutorialFragment newInstance(TutorialType tutorialType) {
TutorialFragment fragment = getFragmentForTutorialType(tutorialType);
if (fragment == null) {
@@ -154,6 +156,8 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
public void onStop() {
super.onStop();
releaseFeedbackVideoView();
releaseGestureVideoView();
mFragmentStopped = true;
}
void initializeFeedbackVideoView() {
@@ -165,8 +169,7 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
Integer introTileStringResId = mTutorialController.getIntroductionTitle();
Integer introSubtitleResId = mTutorialController.getIntroductionSubtitle();
if (introTileStringResId != null && introSubtitleResId != null) {
mTutorialController.showFeedback(introTileStringResId,
introSubtitleResId, null, false);
mTutorialController.showFeedback(introTileStringResId, introSubtitleResId, false);
mIntroductionShown = true;
}
}
@@ -244,7 +247,12 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
@Override
public void onResume() {
super.onResume();
changeController(mTutorialType);
if (mFragmentStopped) {
mTutorialController.showFeedback();
mFragmentStopped = false;
} else {
changeController(mTutorialType);
}
}
@Override
@@ -326,6 +334,10 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
return gestureSandboxActivity == null ? -1 : gestureSandboxActivity.getNumSteps();
}
boolean isAtFinalStep() {
return getCurrentStep() == getNumSteps();
}
@Nullable
private GestureSandboxActivity getGestureSandboxActivity() {
Context context = getContext();

View File

@@ -279,6 +279,7 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
new String[] {
"HOME_NAVIGATION",
"LEFT_EDGE_BACK_NAVIGATION",
"RIGHT_EDGE_BACK_NAVIGATION",
"OVERVIEW_NAVIGATION"}));
return true;
});
@@ -290,7 +291,7 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat {
launchBackTutorialPreference.setOnPreferenceClickListener(preference -> {
startActivity(launchSandboxIntent.putExtra(
"tutorial_steps",
new String[] {"LEFT_EDGE_BACK_NAVIGATION"}));
new String[] {"LEFT_EDGE_BACK_NAVIGATION", "RIGHT_EDGE_BACK_NAVIGATION"}));
return true;
});
sandboxCategory.addPreference(launchBackTutorialPreference);