Adds dummy HomeGestureTutorialFragment.

- Adds a new launch target in Dev options
 - Moves Back handling to the parent TutorialFragment
   (so all Tutorials can handle it as necessary)
 - Currently uses a dummy translating rectangle in
   place of a proper hand animation
 - No actual home gesture recognition is in place yet

Test: Manual
Bug: 148542211
Change-Id: Ic5a545eb9f5003914803272c8ffe367220d63336
This commit is contained in:
Andy Wickham
2020-04-15 20:25:32 +00:00
parent 86932724e7
commit 4f66dc3bef
10 changed files with 260 additions and 58 deletions
+46
View File
@@ -0,0 +1,46 @@
<!--
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.
-->
<!-- Dummy translating rectangle until we have a proper animation. -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt" >
<aapt:attr name="android:drawable">
<vector
android:height="64dp"
android:width="64dp"
android:viewportHeight="600"
android:viewportWidth="600" >
<group
android:name="translationGroup"
android:pivotX="300.0"
android:pivotY="300.0"
android:rotation="180.0" >
<path
android:fillColor="#eeeeee"
android:pathData="M300,70 l 0,-70 70,0 0,140 -70,0 z" />
</group>
</vector>
</aapt:attr>
<target android:name="translationGroup">
<aapt:attr name="android:animation">
<objectAnimator
android:duration="3000"
android:propertyName="translateY"
android:valueFrom="0"
android:valueTo="-100" />
</aapt:attr>
</target>
</animated-vector>
+8 -2
View File
@@ -104,11 +104,17 @@
<!-- Subtitle shown during interactive parts of Back gesture tutorial for left edge. [CHAR LIMIT=60] -->
<string name="back_gesture_tutorial_engaged_subtitle_swipe_inward_left_edge" translatable="false">That\'s it! Now try swiping from the left edge.</string>
<!-- Title shown on the confirmation screen after successful gesture. [CHAR LIMIT=30] -->
<string name="back_gesture_tutorial_confirm_title" translatable="false">All set</string>
<!-- Subtitle shown on the confirmation screen after successful gesture. [CHAR LIMIT=60] -->
<string name="back_gesture_tutorial_confirm_subtitle" translatable="false">To change the sensitivity of the back gesture, go to Settings</string>
<!-- Title shown during interactive part of Home gesture tutorial. [CHAR LIMIT=30] -->
<string name="home_gesture_tutorial_playground_title" translatable="false">Tutorial: Go Home</string>
<!-- Subtitle shown during interactive parts of Home gesture tutorial. [CHAR LIMIT=60] -->
<string name="home_gesture_tutorial_playground_subtitle" translatable="false">Try swiping upward from the bottom edge of the screen</string>
<!-- Title shown on the confirmation screen after successful gesture. [CHAR LIMIT=30] -->
<string name="gesture_tutorial_confirm_title" translatable="false">All set</string>
<!-- Button text shown on a button on the confirm screen. [CHAR LIMIT=14] -->
<string name="gesture_tutorial_action_button_label" translatable="false">Done</string>
<!-- Button text shown on a text button on the confirm screen. [CHAR LIMIT=14] -->
@@ -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();
}
@@ -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);
}
}
}
@@ -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
@@ -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;
}
}
}
@@ -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);
}
}
@@ -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
}
}
@@ -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<? extends TutorialFragment> 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);
}
}
}
@@ -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) {