Merge changes I2cc102d7,Ifba9aa59 into sc-v2-dev am: 54ce7e6cf8

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

Change-Id: I9de621c74f2a47f893d309031ea61e0b25763fcf
This commit is contained in:
TreeHugger Robot
2021-08-17 19:39:18 +00:00
committed by Automerger Merge Worker
17 changed files with 377 additions and 6 deletions
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<ripple
android:color="?android:attr/colorControlHighlight">
<item>
<shape android:shape="rectangle">
<corners android:radius="16dp" />
<solid android:color="?androidprv:attr/colorSurface"/>
<stroke
android:width="1dp"
android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
</shape>
</item>
</ripple>
</inset>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<inset
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<ripple
android:color="?android:attr/colorControlHighlight">
<item>
<shape android:shape="rectangle">
<corners android:radius="16dp"/>
<solid android:color="?androidprv:attr/colorAccentPrimary"/>
</shape>
</item>
</ripple>
</inset>
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

+82
View File
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2021 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.
-->
<com.android.launcher3.taskbar.TaskbarEduView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:gravity="bottom"
android:orientation="vertical"
android:layout_marginHorizontal="108dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/edu_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_rounded_corner_bottom_sheet"
android:gravity="center_horizontal"
android:paddingHorizontal="36dp"
android:paddingTop="64dp">
<TextView
android:id="@+id/edu_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="16dp"
app:layout_constraintTop_toTopOf="parent"
android:gravity="center_horizontal"
style="@style/TextHeadline"
android:text="@string/taskbar_edu_header_1"
android:fontFamily="google-sans"
android:textColor="?android:attr/textColorPrimary"
android:textSize="24sp"
android:maxLines="2"/>
<ImageView
android:id="@+id/edu_illustration"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
app:layout_constraintTop_toBottomOf="@id/edu_header"
android:src="@drawable/taskbar_edu_splitscreen"/>
<Button
android:id="@+id/edu_close_button"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_marginBottom="92dp"
app:layout_constraintTop_toBottomOf="@id/edu_illustration"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="@string/taskbar_edu_close"
style="@style/TaskbarEdu.Button.Close"
android:textColor="?android:attr/textColorPrimary"/>
<Button
android:id="@+id/edu_next_button"
android:layout_width="wrap_content"
android:layout_height="36dp"
android:layout_marginBottom="92dp"
app:layout_constraintTop_toBottomOf="@id/edu_illustration"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="@string/taskbar_edu_next"
style="@style/TaskbarEdu.Button.Next"
android:textColor="?androidprv:attr/textColorOnAccent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</com.android.launcher3.taskbar.TaskbarEduView>
+1
View File
@@ -165,4 +165,5 @@
<dimen name="taskbar_stashed_size">24dp</dimen>
<dimen name="taskbar_stashed_handle_width">220dp</dimen>
<dimen name="taskbar_stashed_handle_height">6dp</dimen>
<dimen name="taskbar_edu_bg_corner_radius">28dp</dimen>
</resources>
+9
View File
@@ -203,4 +203,13 @@
<string name="gesture_tutorial_action_button_label_cancel">Cancel</string>
<!-- Button text shown on a button on the tutorial skip dialog to exit the tutorial. [CHAR LIMIT=14] -->
<string name="gesture_tutorial_action_button_label_skip">Skip</string>
<!-- ******* Taskbar Edu ******* -->
<!-- Text in dialog that lets a user know how they can use the taskbar on their device.
[CHAR_LIMIT=NONE] -->
<string name="taskbar_edu_header_1">Use 2 apps at once and switch apps with the taskbar</string>
<!-- Text on button to go to the next screen of a tutorial [CHAR_LIMIT=30] -->
<string name="taskbar_edu_next">Next</string>
<!-- Text on button to exit a tutorial [CHAR_LIMIT=30] -->
<string name="taskbar_edu_close">Close</string>
</resources>
+12
View File
@@ -139,4 +139,16 @@
<style name="BaseIcon.Workspace.Taskbar" >
<item name="iconDisplay">taskbar</item>
</style>
<style name="TaskbarEdu.Button.Close" parent="@android:style/Widget.Material.Button">
<item name="android:background">@drawable/button_taskbar_edu_bordered</item>
<item name="android:stateListAnimator">@null</item>
<item name="android:textSize">16sp</item>
</style>
<style name="TaskbarEdu.Button.Next" parent="@android:style/Widget.Material.Button">
<item name="android:background">@drawable/button_taskbar_edu_colored</item>
<item name="android:stateListAnimator">@null</item>
<item name="android:textSize">16sp</item>
</style>
</resources>
@@ -670,6 +670,10 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
if (v instanceof BubbleTextView) {
((BubbleTextView) v).setStayPressed(false);
}
LauncherTaskbarUIController taskbarController = mLauncher.getTaskbarUIController();
if (taskbarController != null) {
taskbarController.showEdu();
}
openingTargets.release();
}
});
@@ -32,8 +32,10 @@ import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
@@ -261,6 +263,30 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
mTaskbarOverrideBackgroundAlpha.updateValue(forceHide ? 0 : 1);
}
/**
* Starts the taskbar education flow, if the user hasn't seen it yet.
*/
public void showEdu() {
if (!FeatureFlags.ENABLE_TASKBAR_EDU.get()
|| mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN)) {
return;
}
mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.TASKBAR_EDU_SEEN);
mControllers.taskbarEduController.showEdu();
}
/**
* Manually ends the taskbar education flow.
*/
public void hideEdu() {
if (!FeatureFlags.ENABLE_TASKBAR_EDU.get()) {
return;
}
mControllers.taskbarEduController.hideEdu();
}
private final class TaskBarRecentsAnimationListener implements RecentsAnimationListener {
private final RecentsAnimationCallbacks mCallbacks;
@@ -128,7 +128,8 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
new TaskbarViewController(this, taskbarView),
new TaskbarKeyguardController(this),
new StashedHandleViewController(this, stashedHandleView),
new TaskbarStashController(this));
new TaskbarStashController(this),
new TaskbarEduController(this));
Display display = windowContext.getDisplay();
Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
@@ -34,6 +34,7 @@ public class TaskbarControllers {
public final TaskbarKeyguardController taskbarKeyguardController;
public final StashedHandleViewController stashedHandleViewController;
public final TaskbarStashController taskbarStashController;
public final TaskbarEduController taskbarEduController;
/** Do not store this controller, as it may change at runtime. */
@NonNull public TaskbarUIController uiController = TaskbarUIController.DEFAULT;
@@ -47,7 +48,8 @@ public class TaskbarControllers {
TaskbarViewController taskbarViewController,
TaskbarKeyguardController taskbarKeyguardController,
StashedHandleViewController stashedHandleViewController,
TaskbarStashController taskbarStashController) {
TaskbarStashController taskbarStashController,
TaskbarEduController taskbarEduController) {
this.taskbarActivityContext = taskbarActivityContext;
this.taskbarDragController = taskbarDragController;
this.navButtonController = navButtonController;
@@ -58,6 +60,7 @@ public class TaskbarControllers {
this.taskbarKeyguardController = taskbarKeyguardController;
this.stashedHandleViewController = stashedHandleViewController;
this.taskbarStashController = taskbarStashController;
this.taskbarEduController = taskbarEduController;
}
/**
@@ -0,0 +1,47 @@
/*
* Copyright (C) 2021 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.launcher3.taskbar;
import com.android.launcher3.R;
/** Handles the Taskbar Education flow. */
public class TaskbarEduController {
private final TaskbarActivityContext mActivity;
private TaskbarEduView mTaskbarEduView;
public TaskbarEduController(TaskbarActivityContext activity) {
mActivity = activity;
}
void showEdu() {
mActivity.setTaskbarWindowFullscreen(true);
mActivity.getDragLayer().post(() -> {
mTaskbarEduView = (TaskbarEduView) mActivity.getLayoutInflater().inflate(
R.layout.taskbar_edu, mActivity.getDragLayer(), false);
mTaskbarEduView.addOnCloseListener(() -> {
mTaskbarEduView = null;
});
mTaskbarEduView.show();
});
}
void hideEdu() {
if (mTaskbarEduView != null) {
mTaskbarEduView.close(true /* animate */);
}
}
}
@@ -0,0 +1,113 @@
/*
* Copyright (C) 2021 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.launcher3.taskbar;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import android.animation.PropertyValuesHolder;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.views.AbstractSlideInView;
/** Education view about the Taskbar. */
public class TaskbarEduView extends AbstractSlideInView<TaskbarActivityContext>
implements Insettable {
private static final int DEFAULT_CLOSE_DURATION = 200;
private final Rect mInsets = new Rect();
public TaskbarEduView(Context context, AttributeSet attr) {
this(context, attr, 0);
}
public TaskbarEduView(Context context, AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void handleClose(boolean animate) {
handleClose(animate, DEFAULT_CLOSE_DURATION);
}
@Override
protected boolean isOfType(int type) {
return (type & TYPE_TASKBAR_EDUCATION_DIALOG) != 0;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mContent = findViewById(R.id.edu_view);
findViewById(R.id.edu_close_button).setOnClickListener(v -> close(true /* animate */));
}
@Override
public void setInsets(Rect insets) {
mInsets.set(insets);
mContent.setPadding(mContent.getPaddingStart(),
mContent.getPaddingTop(), mContent.getPaddingEnd(), insets.bottom);
}
@Override
protected void attachToContainer() {
if (mColorScrim != null) {
getPopupContainer().addView(mColorScrim, 0);
}
getPopupContainer().addView(this, 1);
}
/** Show the Education flow. */
public void show() {
attachToContainer();
animateOpen();
}
@Override
protected int getScrimColor(Context context) {
return context.getResources().getColor(R.color.widgets_picker_scrim);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int width = r - l;
int height = b - t;
// Lay out the content as center bottom aligned.
int contentWidth = mContent.getMeasuredWidth();
int contentLeft = (width - contentWidth - mInsets.left - mInsets.right) / 2 + mInsets.left;
mContent.layout(contentLeft, height - mContent.getMeasuredHeight(),
contentLeft + contentWidth, height);
setTranslationShift(mTranslationShift);
}
private void animateOpen() {
if (mIsOpen || mOpenCloseAnimator.isRunning()) {
return;
}
mIsOpen = true;
mOpenCloseAnimator.setValues(
PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
mOpenCloseAnimator.setInterpolator(FAST_OUT_SLOW_IN);
mOpenCloseAnimator.start();
}
}
@@ -288,6 +288,10 @@ public final class LauncherActivityInterface extends
} else {
om.hideOverlay(150);
}
LauncherTaskbarUIController taskbarController = getTaskbarController();
if (taskbarController != null) {
taskbarController.hideEdu();
}
}
@Override
@@ -64,7 +64,8 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
TYPE_OPTIONS_POPUP,
TYPE_ICON_SURFACE,
TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP,
TYPE_WIDGETS_EDUCATION_DIALOG
TYPE_WIDGETS_EDUCATION_DIALOG,
TYPE_TASKBAR_EDUCATION_DIALOG
})
@Retention(RetentionPolicy.SOURCE)
public @interface FloatingViewType {}
@@ -87,18 +88,20 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
public static final int TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP = 1 << 14;
public static final int TYPE_WIDGETS_EDUCATION_DIALOG = 1 << 15;
public static final int TYPE_TASKBAR_EDUCATION_DIALOG = 1 << 16;
public static final int TYPE_ALL = TYPE_FOLDER | TYPE_ACTION_POPUP
| TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGET_RESIZE_FRAME | TYPE_WIDGETS_FULL_SHEET
| TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE | TYPE_TASK_MENU
| TYPE_OPTIONS_POPUP | TYPE_SNACKBAR | TYPE_LISTENER | TYPE_ALL_APPS_EDU
| TYPE_ICON_SURFACE | TYPE_DRAG_DROP_POPUP | TYPE_PIN_WIDGET_FROM_EXTERNAL_POPUP
| TYPE_WIDGETS_EDUCATION_DIALOG;
| TYPE_WIDGETS_EDUCATION_DIALOG | TYPE_TASKBAR_EDUCATION_DIALOG;
// Type of popups which should be kept open during launcher rebind
public static final int TYPE_REBIND_SAFE = TYPE_WIDGETS_FULL_SHEET
| TYPE_WIDGETS_BOTTOM_SHEET | TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
| TYPE_ALL_APPS_EDU | TYPE_ICON_SURFACE | TYPE_WIDGETS_EDUCATION_DIALOG;
| TYPE_ALL_APPS_EDU | TYPE_ICON_SURFACE | TYPE_WIDGETS_EDUCATION_DIALOG
| TYPE_TASKBAR_EDUCATION_DIALOG;
// Usually we show the back button when a floating view is open. Instead, hide for these types.
public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
@@ -219,6 +219,9 @@ public final class FeatureFlags {
public static final BooleanFlag ENABLE_TASKBAR = getDebugFlag(
"ENABLE_TASKBAR", true, "Allows a system Taskbar to be shown on larger devices.");
public static final BooleanFlag ENABLE_TASKBAR_EDU = getDebugFlag("ENABLE_TASKBAR_EDU", false,
"Enables showing taskbar education the first time an app is opened.");
public static final BooleanFlag ENABLE_OVERVIEW_GRID = getDebugFlag(
"ENABLE_OVERVIEW_GRID", true, "Uses grid overview layout. "
+ "Only applicable on large screen devices.");
@@ -38,6 +38,7 @@ public class OnboardingPrefs<T extends Launcher> {
public static final String HOTSEAT_LONGPRESS_TIP_SEEN = "launcher.hotseat_longpress_tip_seen";
public static final String SEARCH_EDU_SEEN = "launcher.search_edu_seen";
public static final String SEARCH_SNACKBAR_COUNT = "launcher.keyboard_snackbar_count";
public static final String TASKBAR_EDU_SEEN = "launcher.taskbar_edu_seen";
/**
* Events that either have happened or have not (booleans).
@@ -45,7 +46,8 @@ public class OnboardingPrefs<T extends Launcher> {
@StringDef(value = {
HOME_BOUNCE_SEEN,
HOTSEAT_LONGPRESS_TIP_SEEN,
SEARCH_EDU_SEEN
SEARCH_EDU_SEEN,
TASKBAR_EDU_SEEN
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventBoolKey {