diff --git a/quickstep/res/drawable/home_gesture.xml b/quickstep/res/drawable/home_gesture.xml new file mode 100644 index 0000000000..c253b7e5c3 --- /dev/null +++ b/quickstep/res/drawable/home_gesture.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml index d7c976de9c..61690aeb10 100644 --- a/quickstep/res/values/strings.xml +++ b/quickstep/res/values/strings.xml @@ -104,11 +104,17 @@ That\'s it! Now try swiping from the left edge. - - All set To change the sensitivity of the back gesture, go to Settings + + + Tutorial: Go Home + + Try swiping upward from the bottom edge of the screen + + + All set Done diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java index 640ae764a5..d58ab5d5b6 100644 --- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialController.java @@ -46,7 +46,7 @@ final class BackGestureTutorialController extends TutorialController { case LEFT_EDGE_BACK_NAVIGATION: return R.string.back_gesture_tutorial_playground_title_swipe_inward_left_edge; case BACK_NAVIGATION_COMPLETE: - return R.string.back_gesture_tutorial_confirm_title; + return R.string.gesture_tutorial_confirm_title; } return null; } @@ -82,10 +82,12 @@ final class BackGestureTutorialController extends TutorialController { @Override void onActionButtonClicked(View button) { - hideHandCoachingAnimation(); - if (button == mActionTextButton) { - mTutorialFragment.startSystemNavigationSetting(); - } + mTutorialFragment.closeTutorial(); + } + + @Override + void onActionTextButtonClicked(View button) { + mTutorialFragment.startSystemNavigationSetting(); mTutorialFragment.closeTutorial(); } diff --git a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java index ddf1cda55c..59067c1cc9 100644 --- a/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/BackGestureTutorialFragment.java @@ -15,29 +15,11 @@ */ package com.android.quickstep.interaction; -import android.os.Bundle; - import com.android.launcher3.R; -import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback; -import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult; import com.android.quickstep.interaction.TutorialController.TutorialType; /** Shows the Back gesture interactive tutorial. */ -public class BackGestureTutorialFragment extends TutorialFragment - implements BackGestureAttemptCallback { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mEdgeBackGestureHandler.registerBackGestureAttemptCallback(this); - } - - @Override - public void onDestroy() { - super.onDestroy(); - mEdgeBackGestureHandler.unregisterBackGestureAttemptCallback(); - } - +public class BackGestureTutorialFragment extends TutorialFragment { @Override int getHandAnimationResId() { return R.drawable.back_gesture; @@ -47,11 +29,4 @@ public class BackGestureTutorialFragment extends TutorialFragment TutorialController createController(TutorialType type) { return new BackGestureTutorialController(this, type); } - - @Override - public void onBackGestureAttempted(BackGestureResult result) { - if (mTutorialController != null) { - mTutorialController.onBackGestureAttempted(result); - } - } } diff --git a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java index 414ddfa73b..f8d9d8d502 100644 --- a/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java +++ b/quickstep/src/com/android/quickstep/interaction/GestureSandboxActivity.java @@ -15,11 +15,12 @@ */ package com.android.quickstep.interaction; +import static com.android.quickstep.interaction.TutorialFragment.KEY_TUTORIAL_TYPE; + import android.graphics.Color; import android.graphics.Rect; import android.os.Bundle; import android.util.DisplayMetrics; -import android.util.Log; import android.view.Display; import android.view.View; import android.view.Window; @@ -44,13 +45,7 @@ public class GestureSandboxActivity extends FragmentActivity { requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.gesture_tutorial_activity); - try { - mFragment = TutorialFragment.newInstance(BackGestureTutorialFragment.class, - TutorialType.RIGHT_EDGE_BACK_NAVIGATION); - } catch (InstantiationException | IllegalAccessException e) { - Log.wtf(LOG_TAG, "Failed to create tutorial fragment!", e); - mFragment = new BackGestureTutorialFragment(); - } + mFragment = TutorialFragment.newInstance(getTutorialType(getIntent().getExtras())); getSupportFragmentManager().beginTransaction() .add(R.id.gesture_tutorial_fragment_container, mFragment) .commit(); @@ -77,6 +72,19 @@ public class GestureSandboxActivity extends FragmentActivity { } } + private TutorialType getTutorialType(Bundle extras) { + TutorialType defaultType = TutorialType.RIGHT_EDGE_BACK_NAVIGATION; + + if (extras == null || !extras.containsKey(KEY_TUTORIAL_TYPE)) { + return defaultType; + } + try { + return TutorialType.valueOf(extras.getString(KEY_TUTORIAL_TYPE, "")); + } catch (IllegalArgumentException e) { + return defaultType; + } + } + private void hideSystemUI() { getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java new file mode 100644 index 0000000000..0bf996dc8e --- /dev/null +++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialController.java @@ -0,0 +1,85 @@ +/* + * 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.quickstep.interaction.TutorialController.TutorialType.HOME_NAVIGATION_COMPLETE; + +import android.view.View; + +import com.android.launcher3.R; +import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult; + +/** A {@link TutorialController} for the Home tutorial. */ +final class HomeGestureTutorialController extends TutorialController { + + HomeGestureTutorialController(HomeGestureTutorialFragment fragment, TutorialType tutorialType) { + super(fragment, tutorialType); + } + + @Override + void transitToController() { + super.transitToController(); + if (mTutorialType != HOME_NAVIGATION_COMPLETE) { + mHandCoachingAnimation.startLoopedAnimation(mTutorialType); + } + } + + @Override + Integer getTitleStringId() { + switch (mTutorialType) { + case HOME_NAVIGATION: + return R.string.home_gesture_tutorial_playground_title; + case HOME_NAVIGATION_COMPLETE: + return R.string.gesture_tutorial_confirm_title; + } + return null; + } + + @Override + Integer getSubtitleStringId() { + if (mTutorialType == TutorialType.HOME_NAVIGATION) { + return R.string.home_gesture_tutorial_playground_subtitle; + } + return null; + } + + @Override + Integer getActionButtonStringId() { + if (mTutorialType == HOME_NAVIGATION_COMPLETE) { + return R.string.gesture_tutorial_action_button_label; + } + return null; + } + + @Override + void onActionButtonClicked(View button) { + mTutorialFragment.closeTutorial(); + } + + @Override + public void onBackGestureAttempted(BackGestureResult result) { + switch (mTutorialType) { + case HOME_NAVIGATION: + break; + case HOME_NAVIGATION_COMPLETE: + if (result == BackGestureResult.BACK_COMPLETED_FROM_LEFT + || result == BackGestureResult.BACK_COMPLETED_FROM_RIGHT) { + mTutorialFragment.closeTutorial(); + } + break; + } + } +} diff --git a/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java new file mode 100644 index 0000000000..613f1888c9 --- /dev/null +++ b/quickstep/src/com/android/quickstep/interaction/HomeGestureTutorialFragment.java @@ -0,0 +1,32 @@ +/* + * 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 com.android.launcher3.R; +import com.android.quickstep.interaction.TutorialController.TutorialType; + +/** Shows the Home gesture interactive tutorial. */ +public class HomeGestureTutorialFragment extends TutorialFragment { + @Override + int getHandAnimationResId() { + return R.drawable.home_gesture; + } + + @Override + TutorialController createController(TutorialType type) { + return new HomeGestureTutorialController(this, type); + } +} diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialController.java b/quickstep/src/com/android/quickstep/interaction/TutorialController.java index cd4d0d80a1..0f9a5d0120 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialController.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialController.java @@ -82,6 +82,8 @@ abstract class TutorialController { void onActionButtonClicked(View button) {} + void onActionTextButtonClicked(View button) {} + void hideHandCoachingAnimation() { mHandCoachingAnimation.stop(); } @@ -112,7 +114,8 @@ abstract class TutorialController { private void updateActionButtons() { updateButton(mActionButton, getActionButtonStringId(), this::onActionButtonClicked); - updateButton(mActionTextButton, getActionTextButtonStringId(), this::onActionButtonClicked); + updateButton( + mActionTextButton, getActionTextButtonStringId(), this::onActionTextButtonClicked); } private void updateButton(Button button, @Nullable Integer stringId, OnClickListener listener) { @@ -131,5 +134,7 @@ abstract class TutorialController { RIGHT_EDGE_BACK_NAVIGATION, LEFT_EDGE_BACK_NAVIGATION, BACK_NAVIGATION_COMPLETE, + HOME_NAVIGATION, + HOME_NAVIGATION_COMPLETE } } diff --git a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java index 09ea8d6b2c..881587de89 100644 --- a/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java +++ b/quickstep/src/com/android/quickstep/interaction/TutorialFragment.java @@ -31,11 +31,13 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import com.android.launcher3.R; +import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureAttemptCallback; +import com.android.quickstep.interaction.EdgeBackGestureHandler.BackGestureResult; import com.android.quickstep.interaction.TutorialController.TutorialType; import java.net.URISyntaxException; -abstract class TutorialFragment extends Fragment { +abstract class TutorialFragment extends Fragment implements BackGestureAttemptCallback { private static final String LOG_TAG = "TutorialFragment"; private static final String SYSTEM_NAVIGATION_SETTING_INTENT = @@ -43,7 +45,7 @@ abstract class TutorialFragment extends Fragment { + ".:settings:fragment_args_key=gesture_system_navigation_input_summary;S" + ".:settings:show_fragment=com.android.settings.gestures" + ".SystemNavigationGestureSettings;end"; - private static final String KEY_TUTORIAL_TYPE = "tutorialType"; + static final String KEY_TUTORIAL_TYPE = "tutorial_type"; TutorialType mTutorialType; @Nullable TutorialController mTutorialController = null; @@ -51,16 +53,34 @@ abstract class TutorialFragment extends Fragment { TutorialHandAnimation mHandCoachingAnimation; EdgeBackGestureHandler mEdgeBackGestureHandler; - public static TutorialFragment newInstance( - Class fragmentClass, TutorialType tutorialType) - throws java.lang.InstantiationException, IllegalAccessException { - TutorialFragment fragment = fragmentClass.newInstance(); + public static TutorialFragment newInstance(TutorialType tutorialType) { + TutorialFragment fragment = getFragmentForTutorialType(tutorialType); + if (fragment == null) { + fragment = new BackGestureTutorialFragment(); + tutorialType = TutorialType.RIGHT_EDGE_BACK_NAVIGATION; + } Bundle args = new Bundle(); args.putSerializable(KEY_TUTORIAL_TYPE, tutorialType); fragment.setArguments(args); return fragment; } + @Nullable + private static TutorialFragment getFragmentForTutorialType(TutorialType tutorialType) { + switch (tutorialType) { + case RIGHT_EDGE_BACK_NAVIGATION: + case LEFT_EDGE_BACK_NAVIGATION: + case BACK_NAVIGATION_COMPLETE: + return new BackGestureTutorialFragment(); + case HOME_NAVIGATION: + case HOME_NAVIGATION_COMPLETE: + return new HomeGestureTutorialFragment(); + default: + Log.e(LOG_TAG, "Failed to find an appropriate fragment for " + tutorialType.name()); + } + return null; + } + abstract int getHandAnimationResId(); abstract TutorialController createController(TutorialType type); @@ -71,6 +91,13 @@ abstract class TutorialFragment extends Fragment { Bundle args = savedInstanceState != null ? savedInstanceState : getArguments(); mTutorialType = (TutorialType) args.getSerializable(KEY_TUTORIAL_TYPE); mEdgeBackGestureHandler = new EdgeBackGestureHandler(getContext()); + mEdgeBackGestureHandler.registerBackGestureAttemptCallback(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mEdgeBackGestureHandler.unregisterBackGestureAttemptCallback(); } @Override @@ -131,6 +158,13 @@ abstract class TutorialFragment extends Fragment { return mHandCoachingAnimation; } + @Override + public void onBackGestureAttempted(BackGestureResult result) { + if (mTutorialController != null) { + mTutorialController.onBackGestureAttempted(result); + } + } + void closeTutorial() { FragmentActivity activity = getActivity(); if (activity != null) { @@ -149,5 +183,4 @@ abstract class TutorialFragment extends Fragment { Log.e(LOG_TAG, "The launch Activity not found: " + e); } } - } diff --git a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java index 8dc2e611e9..5bf91737c1 100644 --- a/src/com/android/launcher3/settings/DeveloperOptionsFragment.java +++ b/src/com/android/launcher3/settings/DeveloperOptionsFragment.java @@ -216,17 +216,27 @@ public class DeveloperOptionsFragment extends PreferenceFragmentCompat { if (launchSandboxIntent.resolveActivity(context.getPackageManager()) == null) { return; } - PreferenceCategory sandboxCategory = newCategory("Sandbox"); - Preference launchSandboxPreference = new Preference(context); - launchSandboxPreference.setKey("launchSandbox"); - launchSandboxPreference.setTitle("Launch Gesture Navigation Sandbox"); - launchSandboxPreference.setSummary( - "This provides tutorials and a place to practice navigation gestures."); - launchSandboxPreference.setOnPreferenceClickListener(preference -> { - startActivity(launchSandboxIntent); + PreferenceCategory sandboxCategory = newCategory("Gesture Navigation Sandbox"); + sandboxCategory.setSummary("Learn and practice navigation gestures"); + Preference launchBackTutorialPreference = new Preference(context); + launchBackTutorialPreference.setKey("launchBackTutorial"); + launchBackTutorialPreference.setTitle("Launch Back Tutorial"); + launchBackTutorialPreference.setSummary("Learn how to use the Back gesture"); + launchBackTutorialPreference.setOnPreferenceClickListener(preference -> { + startActivity(launchSandboxIntent.putExtra( + "tutorial_type", "RIGHT_EDGE_BACK_NAVIGATION")); return true; }); - sandboxCategory.addPreference(launchSandboxPreference); + sandboxCategory.addPreference(launchBackTutorialPreference); + Preference launchHomeTutorialPreference = new Preference(context); + launchHomeTutorialPreference.setKey("launchHomeTutorial"); + launchHomeTutorialPreference.setTitle("Launch Home Tutorial"); + launchHomeTutorialPreference.setSummary("Learn how to use the Home gesture"); + launchHomeTutorialPreference.setOnPreferenceClickListener(preference -> { + startActivity(launchSandboxIntent.putExtra("tutorial_type", "HOME_NAVIGATION")); + return true; + }); + sandboxCategory.addPreference(launchHomeTutorialPreference); } private String toName(String action) {