Merge "Fix broken gesture nav edu on tablets in portrait." into udc-qpr-dev am: d33fc05022

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/24103298

Change-Id: I2097c1f6e9ffef030be22505d6b242509d8adf63
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Schneider Victor-tulias
2023-07-25 17:40:40 +00:00
committed by Automerger Merge Worker
15 changed files with 181 additions and 126 deletions

View File

@@ -13,80 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<androidx.constraintlayout.widget.ConstraintLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/gesture_tutorial_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/gesture_tutorial_fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<RelativeLayout
android:id="@+id/rotation_prompt"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/surfaceHome"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/background"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/rotate_prompt_bg"
android:padding="24dp">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/rotate_tutorial_warning"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/rotate_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:lineSpacingExtra="2sp"
android:text="@string/gesture_tutorial_rotation_prompt_title"
android:textAppearance="@style/rotate_prompt_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/icon"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/rotate_screen_subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="@string/gesture_tutorial_rotation_prompt"
android:textAppearance="@style/rotate_prompt_subtitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/rotate_title"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
android:layout_height="match_parent"/>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/surfaceHome">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/background"
android:layout_width="300dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/rotate_prompt_bg"
android:padding="24dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent">
<ImageView
android:id="@+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/rotate_tutorial_warning"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:id="@+id/rotate_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:lineSpacingExtra="2sp"
android:text="@string/gesture_tutorial_rotation_prompt_title"
android:textAppearance="@style/rotate_prompt_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/icon"
app:layout_constraintEnd_toEndOf="parent" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:gravity="center"
android:text="@string/gesture_tutorial_rotation_prompt"
android:textAppearance="@style/rotate_prompt_subtitle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/rotate_title"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -154,7 +154,7 @@ final class BackGestureTutorialController extends TutorialController {
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (skipGestureAttempt()) {
if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
@@ -172,7 +172,7 @@ final class BackGestureTutorialController extends TutorialController {
@Override
public void onBackGestureProgress(float diffx, float diffy, boolean isLeftGesture) {
if (skipGestureAttempt()) {
if (isGestureCompleted()) {
return;
}
@@ -241,7 +241,7 @@ final class BackGestureTutorialController extends TutorialController {
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
if (skipGestureAttempt()) {
if (isGestureCompleted()) {
return;
}
if (mTutorialType == BACK_NAVIGATION_COMPLETE) {

View File

@@ -42,6 +42,12 @@ public class BackGestureTutorialFragment extends TutorialFragment {
super(fromTutorialMenu);
}
@NonNull
@Override
TutorialType getDefaultTutorialType() {
return TutorialType.BACK_NAVIGATION;
}
@Nullable
@Override
Integer getEdgeAnimationResId() {

View File

@@ -53,16 +53,14 @@ public class GestureSandboxActivity extends FragmentActivity {
static final String KEY_USE_TUTORIAL_MENU = "use_tutorial_menu";
@Nullable private TutorialType[] mTutorialSteps;
private GestureSandboxFragment mFragment;
private GestureSandboxFragment mCurrentFragment;
private GestureSandboxFragment mPendingFragment;
private int mCurrentStep;
private int mNumSteps;
private boolean mShowRotationPrompt;
private SharedPreferences mSharedPrefs;
private StatsLogManager mStatsLogManager;
private View mRotationPrompt;
private TISBindHelper mTISBindHelper;
@Override
@@ -82,7 +80,7 @@ public class GestureSandboxActivity extends FragmentActivity {
&& args.getBoolean(KEY_USE_TUTORIAL_MENU, false)) {
mTutorialSteps = null;
TutorialType tutorialTypeOverride = (TutorialType) args.get(KEY_TUTORIAL_TYPE);
mFragment = tutorialTypeOverride == null
mCurrentFragment = tutorialTypeOverride == null
? new MenuFragment()
: makeTutorialFragment(
tutorialTypeOverride,
@@ -90,16 +88,15 @@ public class GestureSandboxActivity extends FragmentActivity {
/* fromMenu= */ true);
} else {
mTutorialSteps = getTutorialSteps(args);
mFragment = makeTutorialFragment(
mCurrentFragment = makeTutorialFragment(
mTutorialSteps[mCurrentStep - 1],
gestureComplete,
/* fromMenu= */ false);
}
getSupportFragmentManager().beginTransaction()
.add(R.id.gesture_tutorial_fragment_container, mFragment)
.add(R.id.gesture_tutorial_fragment_container, mCurrentFragment)
.commit();
mRotationPrompt = findViewById(R.id.rotation_prompt);
if (FeatureFlags.ENABLE_NEW_GESTURE_NAV_TUTORIAL.get()) {
correctUserOrientation();
}
@@ -127,34 +124,45 @@ public class GestureSandboxActivity extends FragmentActivity {
DeviceProfile deviceProfile = InvariantDeviceProfile.INSTANCE.get(
getApplicationContext()).getDeviceProfile(this);
if (deviceProfile.isTablet) {
mShowRotationPrompt = getResources().getConfiguration().orientation
boolean showRotationPrompt = getResources().getConfiguration().orientation
== ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
updateVisibility(mRotationPrompt, mShowRotationPrompt ? View.VISIBLE : View.GONE);
GestureSandboxFragment recreatedFragment =
showRotationPrompt || mPendingFragment == null
? null : mPendingFragment.recreateFragment();
showFragment(showRotationPrompt
? new RotationPromptFragment()
: recreatedFragment == null
? mCurrentFragment : recreatedFragment);
} else {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
}
void updateVisibility(View view, int visibility) {
if (view == null || view.getVisibility() == visibility) {
return;
private void showFragment(@NonNull GestureSandboxFragment fragment) {
if (mCurrentFragment.recreateFragment() != null) {
mPendingFragment = mCurrentFragment;
}
view.setVisibility(visibility);
mCurrentFragment = fragment;
getSupportFragmentManager().beginTransaction()
.replace(R.id.gesture_tutorial_fragment_container, mCurrentFragment)
.runOnCommit(() -> mCurrentFragment.onAttachedToWindow())
.commit();
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
if (mFragment.shouldDisableSystemGestures()) {
if (mCurrentFragment.shouldDisableSystemGestures()) {
disableSystemGestures();
}
mFragment.onAttachedToWindow();
mCurrentFragment.onAttachedToWindow();
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
mFragment.onDetachedFromWindow();
mCurrentFragment.onDetachedFromWindow();
}
@Override
@@ -169,14 +177,10 @@ public class GestureSandboxActivity extends FragmentActivity {
protected void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
savedInstanceState.putStringArray(KEY_TUTORIAL_STEPS, getTutorialStepNames());
savedInstanceState.putInt(KEY_CURRENT_STEP, mCurrentStep);
mFragment.onSaveInstanceState(savedInstanceState);
mCurrentFragment.onSaveInstanceState(savedInstanceState);
super.onSaveInstanceState(savedInstanceState);
}
protected boolean isRotationPromptShowing() {
return mShowRotationPrompt;
}
protected SharedPreferences getSharedPrefs() {
return mSharedPrefs;
}
@@ -205,7 +209,7 @@ public class GestureSandboxActivity extends FragmentActivity {
*/
public void continueTutorial() {
if (isTutorialComplete() || mTutorialSteps == null) {
mFragment.close();
mCurrentFragment.close();
return;
}
launchTutorialStep(mTutorialSteps[mCurrentStep], false);
@@ -224,20 +228,12 @@ public class GestureSandboxActivity extends FragmentActivity {
* the menu when complete.
*/
public void launchTutorialStep(@NonNull TutorialType tutorialType, boolean fromMenu) {
mFragment = makeTutorialFragment(tutorialType, false, fromMenu);
getSupportFragmentManager().beginTransaction()
.replace(R.id.gesture_tutorial_fragment_container, mFragment)
.runOnCommit(() -> mFragment.onAttachedToWindow())
.commit();
showFragment(makeTutorialFragment(tutorialType, false, fromMenu));
}
/** Launches the gesture nav tutorial menu page */
public void launchTutorialMenu() {
mFragment = new MenuFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.gesture_tutorial_fragment_container, mFragment)
.runOnCommit(() -> mFragment.onAttachedToWindow())
.commit();
showFragment(new MenuFragment());
}
private String[] getTutorialStepNames() {

View File

@@ -17,6 +17,7 @@ package com.android.quickstep.interaction;
import android.app.Activity;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
@@ -27,6 +28,11 @@ public abstract class GestureSandboxFragment extends Fragment {
void onDetachedFromWindow() {}
@Nullable
GestureSandboxFragment recreateFragment() {
return null;
}
boolean shouldDisableSystemGestures() {
return true;
}

View File

@@ -147,7 +147,7 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (skipGestureAttempt()) {
if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
@@ -174,7 +174,7 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
if (skipGestureAttempt()) {
if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {

View File

@@ -41,6 +41,12 @@ public class HomeGestureTutorialFragment extends TutorialFragment {
super(fromTutorialMenu);
}
@NonNull
@Override
TutorialType getDefaultTutorialType() {
return TutorialType.HOME_NAVIGATION;
}
@Nullable
@Override
Integer getEdgeAnimationResId() {

View File

@@ -32,6 +32,12 @@ import com.android.launcher3.R;
/** Displays the gesture nav tutorial menu. */
public final class MenuFragment extends GestureSandboxFragment {
@NonNull
@Override
GestureSandboxFragment recreateFragment() {
return new MenuFragment();
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {

View File

@@ -179,7 +179,7 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
@Override
public void onBackGestureAttempted(BackGestureResult result) {
if (skipGestureAttempt()) {
if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {
@@ -206,7 +206,7 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
@Override
public void onNavBarGestureAttempted(NavBarGestureResult result, PointF finalVelocity) {
if (skipGestureAttempt()) {
if (isGestureCompleted()) {
return;
}
switch (mTutorialType) {

View File

@@ -41,6 +41,12 @@ public class OverviewGestureTutorialFragment extends TutorialFragment {
super(fromTutorialMenu);
}
@NonNull
@Override
TutorialType getDefaultTutorialType() {
return TutorialType.OVERVIEW_NAVIGATION;
}
@Nullable
@Override
Integer getEdgeAnimationResId() {

View File

@@ -0,0 +1,37 @@
/*
* Copyright (C) 2023 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 android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
/** Displays the prompt requesting that the user rotates their device. */
public class RotationPromptFragment extends GestureSandboxFragment {
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.gesture_tutorial_rotation_prompt, container, false);
}
}

View File

@@ -282,7 +282,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
@Override
public void setNavBarGestureProgress(@Nullable Float displacement) {
if (skipGestureAttempt()) {
if (isGestureCompleted()) {
return;
}
if (mTutorialType == HOME_NAVIGATION_COMPLETE
@@ -303,7 +303,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
@Override
public void onMotionPaused(boolean unused) {
if (skipGestureAttempt()) {
if (isGestureCompleted()) {
return;
}
if (mShowTasks) {

View File

@@ -489,10 +489,6 @@ abstract class TutorialController implements BackGestureAttemptCallback,
return mGestureCompleted;
}
public boolean skipGestureAttempt() {
return isGestureCompleted() || mTutorialFragment.isRotationPromptShowing();
}
void hideFeedback() {
if (mFeedbackView.getVisibility() != View.VISIBLE) {
return;

View File

@@ -100,6 +100,19 @@ abstract class TutorialFragment extends GestureSandboxFragment implements OnTouc
return fragment;
}
@Nullable
@Override
GestureSandboxFragment recreateFragment() {
TutorialType tutorialType = mTutorialController == null
? (mTutorialType == null
? getDefaultTutorialType() : mTutorialType)
: mTutorialController.mTutorialType;
return newInstance(tutorialType, isGestureComplete(), mFromTutorialMenu);
}
@NonNull
abstract TutorialType getDefaultTutorialType();
TutorialFragment(boolean fromTutorialMenu) {
mFromTutorialMenu = fromTutorialMenu;
}
@@ -498,11 +511,6 @@ abstract class TutorialFragment extends GestureSandboxFragment implements OnTouc
return activity != null ? activity.getStatsLogManager() : null;
}
protected boolean isRotationPromptShowing() {
GestureSandboxActivity activity = getGestureSandboxActivity();
return activity != null && activity.isRotationPromptShowing();
}
@Nullable
private SharedPreferences getSharedPreferences() {
GestureSandboxActivity activity = getGestureSandboxActivity();