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:
@@ -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>
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user