Implement initial transient Taskbar EDU tooltips.
Since this tooltip looks and behaves differently than the existing EDU sheet, it has its own view and controller implementations (I also may have wanted to write some Kotlin). To keep transient taskbar open while on the second EDU step, another autohide suspend flag is defined. Additionally, special casing is added to avoid hiding transient taskbar if autohiding is currently suspended. Tooltips use the same assets as the bottom sheet for now, and are scaled down to fit the tooltip dimensions. Reset `Taskbar Education` in Developer Options to try EDU again. [Demos] - First: https://screenshot.googleplex.com/ASBeGvrb2EA5wEF.png - Second: https://screenshot.googleplex.com/7fnfcTh9bMYezDc.png Test: Manual Test: Open app, see swipe-up tooltip. Test: Swipe up to show transient taskbar, see features tooltip. Bug: 263157739 Fix: 258460203 Change-Id: I473f5fccbae279db0614763b640da0a120b6b7f7
This commit is contained in:
@@ -699,7 +699,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
LauncherTaskbarUIController taskbarController = mLauncher.getTaskbarUIController();
|
||||
if (taskbarController != null && taskbarController.shouldShowEdu()) {
|
||||
if (taskbarController != null && taskbarController.shouldShowEduOnAppLaunch()) {
|
||||
// LAUNCHER_TASKBAR_EDUCATION_SHOWING is set to true here, when the education
|
||||
// flow is about to start, to avoid a race condition with other components
|
||||
// that would show something else to the user as soon as the app is opened.
|
||||
@@ -715,7 +715,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
}
|
||||
LauncherTaskbarUIController taskbarController = mLauncher.getTaskbarUIController();
|
||||
if (taskbarController != null) {
|
||||
taskbarController.showEdu();
|
||||
taskbarController.showEduOnAppLaunch();
|
||||
}
|
||||
openingTargets.release();
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import android.view.ContextThemeWrapper;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||
import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
@@ -32,10 +34,12 @@ public abstract class BaseTaskbarContext extends ContextThemeWrapper implements
|
||||
|
||||
protected final LayoutInflater mLayoutInflater;
|
||||
private final List<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
|
||||
private final OnboardingPrefs<BaseTaskbarContext> mOnboardingPrefs;
|
||||
|
||||
public BaseTaskbarContext(Context windowContext) {
|
||||
super(windowContext, Themes.getActivityThemeRes(windowContext));
|
||||
mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
|
||||
mOnboardingPrefs = new OnboardingPrefs<>(this, LauncherPrefs.getPrefs(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,6 +52,11 @@ public abstract class BaseTaskbarContext extends ContextThemeWrapper implements
|
||||
return mDPChangeListeners;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OnboardingPrefs<BaseTaskbarContext> getOnboardingPrefs() {
|
||||
return mOnboardingPrefs;
|
||||
}
|
||||
|
||||
/** Callback invoked when a drag is initiated within this context. */
|
||||
public abstract void onDragStart();
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.android.launcher3.taskbar;
|
||||
import static android.view.InsetsState.ITYPE_EXTRA_NAVIGATION_BAR;
|
||||
|
||||
import static com.android.launcher3.QuickstepTransitionManager.TRANSIENT_TASKBAR_TRANSITION_DURATION;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_EDU_TOOLTIP;
|
||||
import static com.android.launcher3.taskbar.TaskbarEduTooltipControllerKt.TOOLTIP_STEP_FEATURES;
|
||||
import static com.android.launcher3.taskbar.TaskbarLauncherStateController.FLAG_RESUMED;
|
||||
import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
|
||||
|
||||
@@ -259,23 +261,51 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the taskbar education flow, if the user hasn't seen it yet.
|
||||
* Starts a Taskbar EDU flow, if the user should see one upon launching an application.
|
||||
*/
|
||||
public void showEdu() {
|
||||
if (!shouldShowEdu()) {
|
||||
public void showEduOnAppLaunch() {
|
||||
if (!shouldShowEduOnAppLaunch()) {
|
||||
return;
|
||||
}
|
||||
mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.TASKBAR_EDU_SEEN);
|
||||
|
||||
mControllers.taskbarEduController.showEdu();
|
||||
// Transient and persistent bottom sheet.
|
||||
if (!ENABLE_TASKBAR_EDU_TOOLTIP.get()) {
|
||||
mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.TASKBAR_EDU_SEEN);
|
||||
mControllers.taskbarEduController.showEdu();
|
||||
return;
|
||||
}
|
||||
|
||||
// Persistent features EDU tooltip.
|
||||
if (!DisplayController.isTransientTaskbar(mLauncher)) {
|
||||
mControllers.taskbarEduTooltipController.maybeShowFeaturesEdu();
|
||||
return;
|
||||
}
|
||||
|
||||
// Transient swipe EDU tooltip.
|
||||
mControllers.taskbarEduTooltipController.maybeShowSwipeEdu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the taskbar education should be shown.
|
||||
* Returns {@code true} if a Taskbar education should be shown on application launch.
|
||||
*/
|
||||
public boolean shouldShowEdu() {
|
||||
return !Utilities.IS_RUNNING_IN_TEST_HARNESS
|
||||
&& !mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN);
|
||||
public boolean shouldShowEduOnAppLaunch() {
|
||||
if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Transient and persistent bottom sheet.
|
||||
if (!ENABLE_TASKBAR_EDU_TOOLTIP.get()) {
|
||||
return !mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN);
|
||||
}
|
||||
|
||||
// Persistent features EDU tooltip.
|
||||
if (!DisplayController.isTransientTaskbar(mLauncher)) {
|
||||
return !mLauncher.getOnboardingPrefs().hasReachedMaxCount(
|
||||
OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP);
|
||||
}
|
||||
|
||||
// Transient swipe EDU tooltip.
|
||||
return mControllers.taskbarEduTooltipController.getTooltipStep() < TOOLTIP_STEP_FEATURES;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -233,7 +233,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
new TaskbarTranslationController(this),
|
||||
isDesktopMode
|
||||
? new DesktopTaskbarRecentAppsController(this)
|
||||
: TaskbarRecentAppsController.DEFAULT);
|
||||
: TaskbarRecentAppsController.DEFAULT,
|
||||
new TaskbarEduTooltipController(this));
|
||||
}
|
||||
|
||||
public void init(@NonNull TaskbarSharedState sharedState) {
|
||||
@@ -915,6 +916,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
*/
|
||||
public void onSwipeToUnstashTaskbar() {
|
||||
mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(false);
|
||||
mControllers.taskbarEduTooltipController.hide();
|
||||
}
|
||||
|
||||
/** Returns {@code true} if taskbar All Apps is open. */
|
||||
|
||||
@@ -39,11 +39,14 @@ public class TaskbarAutohideSuspendController implements
|
||||
public static final int FLAG_AUTOHIDE_SUSPEND_DRAGGING = 1 << 1;
|
||||
// User has touched down but has not lifted finger.
|
||||
public static final int FLAG_AUTOHIDE_SUSPEND_TOUCHING = 1 << 2;
|
||||
// Taskbar EDU overlay is open above the Taskbar. */
|
||||
public static final int FLAG_AUTOHIDE_SUSPEND_EDU_OPEN = 1 << 3;
|
||||
|
||||
@IntDef(flag = true, value = {
|
||||
FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
|
||||
FLAG_AUTOHIDE_SUSPEND_DRAGGING,
|
||||
FLAG_AUTOHIDE_SUSPEND_TOUCHING,
|
||||
FLAG_AUTOHIDE_SUSPEND_EDU_OPEN,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface AutohideSuspendFlag {}
|
||||
@@ -102,6 +105,7 @@ public class TaskbarAutohideSuspendController implements
|
||||
"FLAG_AUTOHIDE_SUSPEND_FULLSCREEN");
|
||||
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_DRAGGING, "FLAG_AUTOHIDE_SUSPEND_DRAGGING");
|
||||
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_TOUCHING, "FLAG_AUTOHIDE_SUSPEND_TOUCHING");
|
||||
appendFlag(str, flags, FLAG_AUTOHIDE_SUSPEND_EDU_OPEN, "FLAG_AUTOHIDE_SUSPEND_EDU_OPEN");
|
||||
return str.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ public class TaskbarControllers {
|
||||
public final TaskbarRecentAppsController taskbarRecentAppsController;
|
||||
public final TaskbarTranslationController taskbarTranslationController;
|
||||
public final TaskbarOverlayController taskbarOverlayController;
|
||||
public final TaskbarEduTooltipController taskbarEduTooltipController;
|
||||
|
||||
@Nullable private LoggableTaskbarController[] mControllersToLog = null;
|
||||
@Nullable private BackgroundRendererController[] mBackgroundRendererControllers = null;
|
||||
@@ -101,7 +102,8 @@ public class TaskbarControllers {
|
||||
TaskbarInsetsController taskbarInsetsController,
|
||||
VoiceInteractionWindowController voiceInteractionWindowController,
|
||||
TaskbarTranslationController taskbarTranslationController,
|
||||
TaskbarRecentAppsController taskbarRecentAppsController) {
|
||||
TaskbarRecentAppsController taskbarRecentAppsController,
|
||||
TaskbarEduTooltipController taskbarEduTooltipController) {
|
||||
this.taskbarActivityContext = taskbarActivityContext;
|
||||
this.taskbarDragController = taskbarDragController;
|
||||
this.navButtonController = navButtonController;
|
||||
@@ -124,6 +126,7 @@ public class TaskbarControllers {
|
||||
this.voiceInteractionWindowController = voiceInteractionWindowController;
|
||||
this.taskbarTranslationController = taskbarTranslationController;
|
||||
this.taskbarRecentAppsController = taskbarRecentAppsController;
|
||||
this.taskbarEduTooltipController = taskbarEduTooltipController;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,6 +158,7 @@ public class TaskbarControllers {
|
||||
voiceInteractionWindowController.init(this);
|
||||
taskbarRecentAppsController.init(this);
|
||||
taskbarTranslationController.init(this);
|
||||
taskbarEduTooltipController.init(this);
|
||||
|
||||
mControllersToLog = new LoggableTaskbarController[] {
|
||||
taskbarDragController, navButtonController, navbarButtonsViewController,
|
||||
@@ -162,7 +166,8 @@ public class TaskbarControllers {
|
||||
taskbarUnfoldAnimationController, taskbarKeyguardController,
|
||||
stashedHandleViewController, taskbarStashController, taskbarEduController,
|
||||
taskbarAutohideSuspendController, taskbarPopupController, taskbarInsetsController,
|
||||
voiceInteractionWindowController, taskbarTranslationController
|
||||
voiceInteractionWindowController, taskbarTranslationController,
|
||||
taskbarEduTooltipController
|
||||
};
|
||||
mBackgroundRendererControllers = new BackgroundRendererController[] {
|
||||
taskbarDragLayerController, taskbarScrimViewController,
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* 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.launcher3.taskbar
|
||||
|
||||
import android.animation.AnimatorSet
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.provider.Settings
|
||||
import android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING
|
||||
import android.util.AttributeSet
|
||||
import android.view.MotionEvent
|
||||
import android.view.MotionEvent.ACTION_DOWN
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.animation.Interpolator
|
||||
import com.android.launcher3.AbstractFloatingView
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.anim.AnimatorListeners
|
||||
import com.android.launcher3.popup.RoundedArrowDrawable
|
||||
import com.android.launcher3.util.Themes
|
||||
import com.android.launcher3.views.ActivityContext
|
||||
import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
|
||||
import com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE
|
||||
import com.android.systemui.animation.Interpolators.STANDARD
|
||||
|
||||
private const val ENTER_DURATION_MS = 300L
|
||||
private const val EXIT_DURATION_MS = 150L
|
||||
|
||||
/** Floating tooltip for Taskbar education. */
|
||||
class TaskbarEduTooltip
|
||||
@JvmOverloads
|
||||
constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0,
|
||||
) : AbstractFloatingView(context, attrs, defStyleAttr) {
|
||||
|
||||
private val activityContext: ActivityContext = ActivityContext.lookupContext(context)
|
||||
|
||||
private val backgroundColor =
|
||||
Themes.getAttrColor(context, com.android.internal.R.attr.colorSurface)
|
||||
|
||||
private val tooltipCornerRadius = Themes.getDialogCornerRadius(context)
|
||||
private val arrowWidth = resources.getDimension(R.dimen.popup_arrow_width)
|
||||
private val arrowHeight = resources.getDimension(R.dimen.popup_arrow_height)
|
||||
private val arrowPointRadius = resources.getDimension(R.dimen.popup_arrow_corner_radius)
|
||||
|
||||
private val enterYDelta = resources.getDimension(R.dimen.taskbar_edu_tooltip_enter_y_delta)
|
||||
private val exitYDelta = resources.getDimension(R.dimen.taskbar_edu_tooltip_exit_y_delta)
|
||||
|
||||
/** Container where the tooltip's body should be inflated. */
|
||||
lateinit var content: ViewGroup
|
||||
private set
|
||||
private lateinit var arrow: View
|
||||
|
||||
/** Callback invoked when the tooltip is being closed. */
|
||||
var onCloseCallback: () -> Unit = {}
|
||||
private var openCloseAnimator: AnimatorSet? = null
|
||||
|
||||
/** Animates the tooltip into view. */
|
||||
fun show() {
|
||||
if (isOpen) {
|
||||
return
|
||||
}
|
||||
mIsOpen = true
|
||||
activityContext.dragLayer.addView(this)
|
||||
openCloseAnimator = createOpenCloseAnimator(isOpening = true).apply { start() }
|
||||
}
|
||||
|
||||
override fun onFinishInflate() {
|
||||
super.onFinishInflate()
|
||||
|
||||
content = findViewById(R.id.content)
|
||||
arrow = findViewById(R.id.arrow)
|
||||
arrow.background =
|
||||
RoundedArrowDrawable(
|
||||
arrowWidth,
|
||||
arrowHeight,
|
||||
arrowPointRadius,
|
||||
tooltipCornerRadius,
|
||||
measuredWidth.toFloat(),
|
||||
measuredHeight.toFloat(),
|
||||
(measuredWidth - arrowWidth) / 2, // arrowOffsetX
|
||||
0f, // arrowOffsetY
|
||||
false, // isPointingUp
|
||||
true, // leftAligned
|
||||
backgroundColor,
|
||||
)
|
||||
}
|
||||
|
||||
override fun handleClose(animate: Boolean) {
|
||||
if (!isOpen) {
|
||||
return
|
||||
}
|
||||
|
||||
onCloseCallback()
|
||||
if (!animate) {
|
||||
return closeComplete()
|
||||
}
|
||||
|
||||
openCloseAnimator?.cancel()
|
||||
openCloseAnimator = createOpenCloseAnimator(isOpening = false)
|
||||
openCloseAnimator?.addListener(AnimatorListeners.forEndCallback(this::closeComplete))
|
||||
openCloseAnimator?.start()
|
||||
}
|
||||
|
||||
override fun isOfType(type: Int): Boolean = type and TYPE_TASKBAR_EDUCATION_DIALOG != 0
|
||||
|
||||
override fun onControllerInterceptTouchEvent(ev: MotionEvent?): Boolean {
|
||||
if (ev?.action == ACTION_DOWN && !activityContext.dragLayer.isEventOverView(this, ev)) {
|
||||
close(true)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow()
|
||||
Settings.Secure.putInt(mContext.contentResolver, LAUNCHER_TASKBAR_EDUCATION_SHOWING, 0)
|
||||
}
|
||||
|
||||
private fun closeComplete() {
|
||||
openCloseAnimator?.cancel()
|
||||
openCloseAnimator = null
|
||||
mIsOpen = false
|
||||
activityContext.dragLayer.removeView(this)
|
||||
}
|
||||
|
||||
private fun createOpenCloseAnimator(isOpening: Boolean): AnimatorSet {
|
||||
val duration: Long
|
||||
val alphaValues: FloatArray
|
||||
val translateYValues: FloatArray
|
||||
val fadeInterpolator: Interpolator
|
||||
val translateYInterpolator: Interpolator
|
||||
|
||||
if (isOpening) {
|
||||
duration = ENTER_DURATION_MS
|
||||
alphaValues = floatArrayOf(0f, 1f)
|
||||
translateYValues = floatArrayOf(enterYDelta, 0f)
|
||||
fadeInterpolator = STANDARD
|
||||
translateYInterpolator = EMPHASIZED_DECELERATE
|
||||
} else {
|
||||
duration = EXIT_DURATION_MS
|
||||
alphaValues = floatArrayOf(1f, 0f)
|
||||
translateYValues = floatArrayOf(0f, exitYDelta)
|
||||
fadeInterpolator = EMPHASIZED_ACCELERATE
|
||||
translateYInterpolator = EMPHASIZED_ACCELERATE
|
||||
}
|
||||
|
||||
val fade =
|
||||
ValueAnimator.ofFloat(*alphaValues).apply {
|
||||
interpolator = fadeInterpolator
|
||||
addUpdateListener {
|
||||
val alpha = it.animatedValue as Float
|
||||
content.alpha = alpha
|
||||
arrow.alpha = alpha
|
||||
}
|
||||
}
|
||||
|
||||
val translateY =
|
||||
ValueAnimator.ofFloat(*translateYValues).apply {
|
||||
interpolator = translateYInterpolator
|
||||
addUpdateListener {
|
||||
val translationY = it.animatedValue as Float
|
||||
content.translationY = translationY
|
||||
arrow.translationY = translationY
|
||||
}
|
||||
}
|
||||
|
||||
return AnimatorSet().apply {
|
||||
this.duration = duration
|
||||
playTogether(fade, translateY)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.launcher3.taskbar
|
||||
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.IntDef
|
||||
import androidx.annotation.LayoutRes
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.Utilities.IS_RUNNING_IN_TEST_HARNESS
|
||||
import com.android.launcher3.config.FeatureFlags.ENABLE_TASKBAR_EDU_TOOLTIP
|
||||
import com.android.launcher3.taskbar.TaskbarAutohideSuspendController.FLAG_AUTOHIDE_SUSPEND_EDU_OPEN
|
||||
import com.android.launcher3.taskbar.TaskbarControllers.LoggableTaskbarController
|
||||
import com.android.launcher3.util.DisplayController
|
||||
import com.android.launcher3.util.OnboardingPrefs.TASKBAR_EDU_TOOLTIP_STEP
|
||||
import java.io.PrintWriter
|
||||
|
||||
/** First EDU step for swiping up to show transient Taskbar. */
|
||||
const val TOOLTIP_STEP_SWIPE = 0
|
||||
/** Second EDU step for explaining Taskbar functionality when unstashed. */
|
||||
const val TOOLTIP_STEP_FEATURES = 1
|
||||
/**
|
||||
* EDU is completed.
|
||||
*
|
||||
* This value should match the maximum count for [TASKBAR_EDU_TOOLTIP_STEP].
|
||||
*/
|
||||
const val TOOLTIP_STEP_NONE = 2
|
||||
|
||||
/** Current step in the tooltip EDU flow. */
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@IntDef(TOOLTIP_STEP_SWIPE, TOOLTIP_STEP_FEATURES, TOOLTIP_STEP_NONE)
|
||||
annotation class TaskbarEduTooltipStep
|
||||
|
||||
/** Controls stepping through the Taskbar tooltip EDU. */
|
||||
class TaskbarEduTooltipController(val activityContext: TaskbarActivityContext) :
|
||||
LoggableTaskbarController {
|
||||
|
||||
private val isTooltipEnabled = !IS_RUNNING_IN_TEST_HARNESS && ENABLE_TASKBAR_EDU_TOOLTIP.get()
|
||||
private val isOpen: Boolean
|
||||
get() = tooltip?.isOpen ?: false
|
||||
|
||||
private lateinit var controllers: TaskbarControllers
|
||||
|
||||
@TaskbarEduTooltipStep
|
||||
var tooltipStep: Int
|
||||
get() {
|
||||
return activityContext.onboardingPrefs?.getCount(TASKBAR_EDU_TOOLTIP_STEP)
|
||||
?: TOOLTIP_STEP_NONE
|
||||
}
|
||||
private set(step) {
|
||||
activityContext.onboardingPrefs?.setEventCount(step, TASKBAR_EDU_TOOLTIP_STEP)
|
||||
}
|
||||
|
||||
private var tooltip: TaskbarEduTooltip? = null
|
||||
|
||||
fun init(controllers: TaskbarControllers) {
|
||||
this.controllers = controllers
|
||||
}
|
||||
|
||||
/** Shows swipe EDU tooltip if it is the current [tooltipStep]. */
|
||||
fun maybeShowSwipeEdu() {
|
||||
if (
|
||||
!isTooltipEnabled ||
|
||||
!DisplayController.isTransientTaskbar(activityContext) ||
|
||||
tooltipStep > TOOLTIP_STEP_SWIPE
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
tooltipStep = TOOLTIP_STEP_FEATURES
|
||||
inflateTooltip(R.layout.taskbar_edu_swipe)
|
||||
tooltip?.show()
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows feature EDU tooltip if this step has not been seen.
|
||||
*
|
||||
* If [TOOLTIP_STEP_SWIPE] has not been seen at this point, the first step is skipped because a
|
||||
* swipe up is necessary to show this step.
|
||||
*/
|
||||
fun maybeShowFeaturesEdu() {
|
||||
if (!isTooltipEnabled || tooltipStep > TOOLTIP_STEP_FEATURES) {
|
||||
return
|
||||
}
|
||||
|
||||
tooltipStep = TOOLTIP_STEP_NONE
|
||||
inflateTooltip(R.layout.taskbar_edu_features)
|
||||
tooltip?.apply {
|
||||
findViewById<View>(R.id.done_button)?.setOnClickListener { hide() }
|
||||
if (DisplayController.isTransientTaskbar(activityContext)) {
|
||||
(layoutParams as ViewGroup.MarginLayoutParams).bottomMargin +=
|
||||
activityContext.deviceProfile.taskbarSize
|
||||
}
|
||||
show()
|
||||
}
|
||||
}
|
||||
|
||||
/** Closes the current [tooltip]. */
|
||||
fun hide() = tooltip?.close(true)
|
||||
|
||||
/** Initializes [tooltip] with content from [contentResId]. */
|
||||
private fun inflateTooltip(@LayoutRes contentResId: Int) {
|
||||
val overlayContext = controllers.taskbarOverlayController.requestWindow()
|
||||
val tooltip =
|
||||
overlayContext.layoutInflater.inflate(
|
||||
R.layout.taskbar_edu_tooltip,
|
||||
overlayContext.dragLayer,
|
||||
false
|
||||
) as TaskbarEduTooltip
|
||||
|
||||
controllers.taskbarAutohideSuspendController.updateFlag(
|
||||
FLAG_AUTOHIDE_SUSPEND_EDU_OPEN,
|
||||
true
|
||||
)
|
||||
tooltip.onCloseCallback = {
|
||||
this.tooltip = null
|
||||
controllers.taskbarAutohideSuspendController.updateFlag(
|
||||
FLAG_AUTOHIDE_SUSPEND_EDU_OPEN,
|
||||
false
|
||||
)
|
||||
controllers.taskbarStashController.updateAndAnimateTransientTaskbar(true)
|
||||
}
|
||||
|
||||
overlayContext.layoutInflater.inflate(contentResId, tooltip.content, true)
|
||||
this.tooltip = tooltip
|
||||
}
|
||||
|
||||
override fun dumpLogs(prefix: String?, pw: PrintWriter?) {
|
||||
pw?.println("$(prefix)TaskbarEduController:")
|
||||
pw?.println("$prefix\tisTooltipEnabled=$isTooltipEnabled")
|
||||
pw?.println("$prefix\tisOpen=$isOpen")
|
||||
pw?.println("$prefix\ttooltipStep=$tooltipStep")
|
||||
}
|
||||
}
|
||||
@@ -426,6 +426,11 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
return;
|
||||
}
|
||||
|
||||
if (stash && mControllers.taskbarAutohideSuspendController.isSuspended()) {
|
||||
// Avoid stashing if autohide is currently suspended.
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasAnyFlag(FLAG_STASHED_IN_APP_AUTO) != stash) {
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_AUTO, stash);
|
||||
applyState();
|
||||
|
||||
@@ -109,8 +109,12 @@ public class TaskbarTranslationController implements TaskbarControllers.Loggable
|
||||
.setStiffness(SpringForce.STIFFNESS_LOW)
|
||||
.build(mTranslationYForSwipe, VALUE);
|
||||
mSpringBounce.addListener(forEndCallback(() -> {
|
||||
if (mGestureEnded) {
|
||||
reset();
|
||||
if (!mGestureEnded) {
|
||||
return;
|
||||
}
|
||||
reset();
|
||||
if (mControllers.taskbarStashController.isInAppAndNotStashed()) {
|
||||
mControllers.taskbarEduTooltipController.maybeShowFeaturesEdu();
|
||||
}
|
||||
}));
|
||||
mSpringBounce.start();
|
||||
|
||||
@@ -19,7 +19,6 @@ import android.content.Context;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.LauncherPrefs;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
@@ -30,7 +29,6 @@ import com.android.launcher3.taskbar.TaskbarControllers;
|
||||
import com.android.launcher3.taskbar.TaskbarDragController;
|
||||
import com.android.launcher3.taskbar.TaskbarStashController;
|
||||
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
|
||||
/**
|
||||
* Window context for the taskbar overlays such as All Apps and EDU.
|
||||
@@ -40,7 +38,6 @@ import com.android.launcher3.util.OnboardingPrefs;
|
||||
*/
|
||||
public class TaskbarOverlayContext extends BaseTaskbarContext {
|
||||
private final TaskbarActivityContext mTaskbarContext;
|
||||
private final OnboardingPrefs<TaskbarOverlayContext> mOnboardingPrefs;
|
||||
|
||||
private final TaskbarOverlayController mOverlayController;
|
||||
private final TaskbarDragController mDragController;
|
||||
@@ -59,7 +56,6 @@ public class TaskbarOverlayContext extends BaseTaskbarContext {
|
||||
mOverlayController = controllers.taskbarOverlayController;
|
||||
mDragController = new TaskbarDragController(this);
|
||||
mDragController.init(controllers);
|
||||
mOnboardingPrefs = new OnboardingPrefs<>(this, LauncherPrefs.getPrefs(this));
|
||||
mDragLayer = new TaskbarOverlayDragLayer(this);
|
||||
|
||||
TaskbarStashController taskbarStashController = controllers.taskbarStashController;
|
||||
@@ -99,11 +95,6 @@ public class TaskbarOverlayContext extends BaseTaskbarContext {
|
||||
return mDragLayer.findViewById(R.id.apps_view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OnboardingPrefs<TaskbarOverlayContext> getOnboardingPrefs() {
|
||||
return mOnboardingPrefs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBindingItems() {
|
||||
return mTaskbarContext.isBindingItems();
|
||||
|
||||
Reference in New Issue
Block a user