diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index f87138e536..beb2a6a156 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -215,10 +215,8 @@ public class QuickstepLauncher extends BaseQuickstepLauncher { switch (state.ordinal) { case HINT_STATE_ORDINAL: { Workspace workspace = getWorkspace(); - boolean willMoveScreens = workspace.getNextPage() != Workspace.DEFAULT_PAGE; - getStateManager().goToState(NORMAL, true, - willMoveScreens ? null : getScrimView()::startDragHandleEducationAnim); - if (willMoveScreens) { + getStateManager().goToState(NORMAL); + if (workspace.getNextPage() != Workspace.DEFAULT_PAGE) { workspace.post(workspace::moveToDefaultScreen); } break; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java index 0a4cec7759..f31bc19c06 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java @@ -38,11 +38,9 @@ import android.widget.FrameLayout; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.Hotseat; import com.android.launcher3.LauncherState; -import com.android.launcher3.anim.Interpolators; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.StateManager.StateListener; import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper; -import com.android.launcher3.views.ScrimView; import com.android.quickstep.LauncherActivityInterface; import com.android.quickstep.SysUINavigationMode; import com.android.systemui.plugins.PluginListener; @@ -126,12 +124,6 @@ public class LauncherRecentsView extends RecentsView } anim.play(ObjectAnimator.ofFloat( mActivity.getAllAppsController(), ALL_APPS_PROGRESS, allAppsProgressOffscreen)); - - ObjectAnimator dragHandleAnim = ObjectAnimator.ofInt( - mActivity.getScrimView(), ScrimView.DRAG_HANDLE_ALPHA, 0); - dragHandleAnim.setInterpolator(Interpolators.ACCEL_2); - anim.play(dragHandleAnim); - return anim; } diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java index 9ed2bbef38..c2e67c1f2f 100644 --- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java +++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java @@ -87,20 +87,6 @@ public class QuickstepOnboardingPrefs extends OnboardingPrefs() { - @Override - public void onStateTransitionComplete(LauncherState finalState) { - if (finalState == ALL_APPS) { - if (incrementEventCount(ALL_APPS_COUNT)) { - stateManager.removeStateListener(this); - mLauncher.getScrimView().updateDragHandleVisibility(); - } - } - } - }); - } - if (FeatureFlags.ENABLE_HYBRID_HOTSEAT.get() && !hasReachedMaxCount( HOTSEAT_DISCOVERY_TIP_COUNT)) { stateManager.addStateListener(new StateListener() { diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java index 19e278be3c..f1ac6a5b94 100644 --- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java +++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java @@ -44,7 +44,6 @@ import com.android.launcher3.Utilities; import com.android.launcher3.anim.Interpolators; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.uioverrides.states.OverviewState; -import com.android.launcher3.util.OnboardingPrefs; import com.android.launcher3.util.Themes; import com.android.launcher3.views.ScrimView; import com.android.quickstep.SysUINavigationMode; @@ -77,15 +76,11 @@ public class ShelfScrimView extends ScrimView private final float mRadius; private final int mMaxScrimAlpha; private final Paint mPaint; - private final OnboardingPrefs mOnboardingPrefs; // Mid point where the alpha changes private int mMidAlpha; private float mMidProgress; - // The progress at which the drag handle starts moving up with the shelf. - private float mDragHandleProgress; - private Interpolator mBeforeMidProgressColorInterpolator = ACCEL; private Interpolator mAfterMidProgressColorInterpolator = ACCEL; @@ -103,7 +98,6 @@ public class ShelfScrimView extends ScrimView private boolean mRemainingScreenPathValid = false; private Mode mSysUINavigationMode; - private boolean mIsTwoZoneSwipeModel; public ShelfScrimView(Context context, AttributeSet attrs) { super(context, attrs); @@ -112,7 +106,6 @@ public class ShelfScrimView extends ScrimView mEndAlpha = Color.alpha(mEndScrim); mRadius = BOTTOM_CORNER_RADIUS_RATIO * Themes.getDialogCornerRadius(context); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mOnboardingPrefs = mLauncher.getOnboardingPrefs(); // Just assume the easiest UI for now, until we have the proper layout information. mDrawingFlatColor = true; @@ -145,11 +138,9 @@ public class ShelfScrimView extends ScrimView // Show the shelf more quickly before reaching overview progress. mBeforeMidProgressColorInterpolator = ACCEL_2; mAfterMidProgressColorInterpolator = ACCEL; - mIsTwoZoneSwipeModel = FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get(); } else { mBeforeMidProgressColorInterpolator = ACCEL; mAfterMidProgressColorInterpolator = Interpolators.clampToProgress(ACCEL, 0.5f, 1f); - mIsTwoZoneSwipeModel = false; } } @@ -164,7 +155,6 @@ public class ShelfScrimView extends ScrimView Context context = getContext(); if ((OVERVIEW.getVisibleElements(mLauncher) & ALL_APPS_HEADER_EXTRA) == 0) { - mDragHandleProgress = 1; if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() && SysUINavigationMode.removeShelfFromOverview(context)) { // Fade in all apps background quickly to distinguish from swiping from nav bar. @@ -182,29 +172,22 @@ public class ShelfScrimView extends ScrimView + hotseatPadding.bottom + hotseatPadding.top; float dragHandleTop = Math.min(hotseatSize, LayoutUtils.getDefaultSwipeHeight(context, dp)); - mDragHandleProgress = 1 - (dragHandleTop / mShiftRange); } - mTopOffset = dp.getInsets().top - mDragHandleSize.y; + mTopOffset = dp.getInsets().top; mShelfTopAtThreshold = mShiftRange * SCRIM_CATCHUP_THRESHOLD + mTopOffset; } updateColors(); updateSysUiColors(); - updateDragHandleAlpha(); invalidate(); } @Override public void updateColors() { super.updateColors(); - mDragHandleOffset = 0; if (mDrawingFlatColor) { return; } - if (mProgress < mDragHandleProgress) { - mDragHandleOffset = mShiftRange * (mDragHandleProgress - mProgress); - } - if (mProgress >= SCRIM_CATCHUP_THRESHOLD) { mShelfTop = mShiftRange * mProgress + mTopOffset; } else { @@ -258,20 +241,8 @@ public class ShelfScrimView extends ScrimView } } - @Override - protected boolean shouldDragHandleBeVisible() { - boolean needsAllAppsEdu = mIsTwoZoneSwipeModel - && !mOnboardingPrefs.hasReachedMaxCount(OnboardingPrefs.ALL_APPS_COUNT); - return needsAllAppsEdu || super.shouldDragHandleBeVisible(); - } - @Override protected void onDraw(Canvas canvas) { - drawBackground(canvas); - drawDragHandle(canvas); - } - - private void drawBackground(Canvas canvas) { if (mDrawingFlatColor) { if (mCurrentFlatColor != 0) { canvas.drawColor(mCurrentFlatColor); @@ -311,9 +282,4 @@ public class ShelfScrimView extends ScrimView mPaint.setColor(mShelfColor); canvas.drawRoundRect(0, mShelfTop, width, height + mRadius, mRadius, mRadius, mPaint); } - - @Override - public float getVisualTop() { - return mShelfTop; - } } diff --git a/res/drawable-v24/drag_handle_indicator_shadow.xml b/res/drawable-v24/drag_handle_indicator_shadow.xml deleted file mode 100644 index 774bc38ceb..0000000000 --- a/res/drawable-v24/drag_handle_indicator_shadow.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - diff --git a/res/drawable/drag_handle_indicator_no_shadow.xml b/res/drawable/drag_handle_indicator_no_shadow.xml deleted file mode 100644 index 341e60cda9..0000000000 --- a/res/drawable/drag_handle_indicator_no_shadow.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - - - diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml index a13790826b..0c18c8a2ba 100644 --- a/res/layout/launcher.xml +++ b/res/layout/launcher.xml @@ -28,6 +28,12 @@ android:clipToPadding="false" android:importantForAccessibility="no"> + + 1dp 0dp - - 4dp - 18dp - 6dp - 1dp - 48dp - 16dp - 48dp 20dp diff --git a/res/values/drawables.xml b/res/values/drawables.xml index 7d631426cb..9c57ec1214 100644 --- a/res/values/drawables.xml +++ b/res/values/drawables.xml @@ -18,5 +18,4 @@ @drawable/ic_remove_no_shadow @drawable/ic_uninstall_no_shadow @drawable/ic_block_no_shadow - @drawable/drag_handle_indicator_no_shadow \ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 80b511a54c..12beeeb566 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -36,7 +36,7 @@ Shortcut isn\'t available - Home screen + Home Custom actions @@ -88,10 +88,6 @@ Personal apps list Work apps list - - Home - Remove diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index e49c4559f0..f9fba6f80f 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -453,10 +453,10 @@ public class Launcher extends StatefulActivity implements Launche mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); } else if (finalState == OVERVIEW || finalState == OVERVIEW_PEEK) { mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); - mScrimView.getAlphaProperty(SCRIM_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); + mScrimView.setAlpha(alpha); } else { mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(1f); - mScrimView.getAlphaProperty(SCRIM_VIEW_ALPHA_CHANNEL_INDEX).setValue(1f); + mScrimView.setAlpha(1f); } } }); @@ -553,7 +553,7 @@ public class Launcher extends StatefulActivity implements Launche mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); } else if (state == OVERVIEW || state == OVERVIEW_PEEK) { mAppsView.getAlphaProperty(APPS_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); - mScrimView.getAlphaProperty(SCRIM_VIEW_ALPHA_CHANNEL_INDEX).setValue(alpha); + mScrimView.setAlpha(alpha); } } @@ -1936,7 +1936,7 @@ public class Launcher extends StatefulActivity implements Launche // Populate event with a fake title based on the current state. // TODO: When can workspace be null? text.add(mWorkspace == null - ? getString(R.string.all_apps_home_button_label) + ? getString(R.string.home_screen) : mStateManager.getState().getDescription(this)); return result; } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 15e0daa8ea..3be9ac7e07 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -3263,7 +3263,7 @@ public class Workspace extends PagedView } if (nScreens == 0) { // When the workspace is not loaded, we do not know how many screen will be bound. - return getContext().getString(R.string.all_apps_home_button_label); + return getContext().getString(R.string.home_screen); } return getContext().getString(R.string.workspace_scroll_format, page + 1, nScreens); } diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 2b816a08a8..0268b9638f 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -19,7 +19,6 @@ import static com.android.launcher3.LauncherState.ALL_APPS_CONTENT; import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA; import static com.android.launcher3.LauncherState.APPS_VIEW_ITEM_MASK; import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.launcher3.LauncherState.VERTICAL_SWIPE_INDICATOR; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.FINAL_FRAME; import static com.android.launcher3.anim.Interpolators.INSTANT; @@ -223,9 +222,6 @@ public class AllAppsTransitionController implements StateHandler, mAppsView.getSearchUiManager().setContentVisibility(visibleElements, setter, allAppsFade); - setter.setInt(mScrimView, ScrimView.DRAG_HANDLE_ALPHA, - (visibleElements & VERTICAL_SWIPE_INDICATOR) != 0 ? 255 : 0, allAppsFade); - // Set visibility of the container at the very beginning or end of the transition. setter.setViewAlpha(mAppsView, hasAnyVisibleItem ? 1 : 0, hasAnyVisibleItem ? INSTANT : FINAL_FRAME); diff --git a/src/com/android/launcher3/util/OnboardingPrefs.java b/src/com/android/launcher3/util/OnboardingPrefs.java index 26313e5a21..6e5e7d9355 100644 --- a/src/com/android/launcher3/util/OnboardingPrefs.java +++ b/src/com/android/launcher3/util/OnboardingPrefs.java @@ -36,7 +36,6 @@ public class OnboardingPrefs { public static final String SHELF_BOUNCE_SEEN = "launcher.shelf_bounce_seen"; public static final String HOME_BOUNCE_COUNT = "launcher.home_bounce_count"; public static final String SHELF_BOUNCE_COUNT = "launcher.shelf_bounce_count"; - public static final String ALL_APPS_COUNT = "launcher.all_apps_count"; public static final String HOTSEAT_DISCOVERY_TIP_COUNT = "launcher.hotseat_discovery_tip_count"; public static final String HOTSEAT_LONGPRESS_TIP_SEEN = "launcher.hotseat_longpress_tip_seen"; @@ -56,7 +55,6 @@ public class OnboardingPrefs { @StringDef(value = { HOME_BOUNCE_COUNT, SHELF_BOUNCE_COUNT, - ALL_APPS_COUNT, HOTSEAT_DISCOVERY_TIP_COUNT }) @Retention(RetentionPolicy.SOURCE) @@ -67,7 +65,6 @@ public class OnboardingPrefs { Map maxCounts = new ArrayMap<>(4); maxCounts.put(HOME_BOUNCE_COUNT, 3); maxCounts.put(SHELF_BOUNCE_COUNT, 3); - maxCounts.put(ALL_APPS_COUNT, 5); maxCounts.put(HOTSEAT_DISCOVERY_TIP_COUNT, 5); MAX_COUNTS = Collections.unmodifiableMap(maxCounts); } diff --git a/src/com/android/launcher3/views/AccessibilityActionsView.java b/src/com/android/launcher3/views/AccessibilityActionsView.java new file mode 100644 index 0000000000..0eacaa3009 --- /dev/null +++ b/src/com/android/launcher3/views/AccessibilityActionsView.java @@ -0,0 +1,97 @@ +/* + * 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.launcher3.views; + +import static com.android.launcher3.LauncherState.ALL_APPS; +import static com.android.launcher3.LauncherState.NORMAL; + +import android.content.Context; +import android.os.Bundle; +import android.util.AttributeSet; +import android.view.View; +import android.view.accessibility.AccessibilityNodeInfo; +import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; + +import androidx.annotation.Nullable; + +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherState; +import com.android.launcher3.R; +import com.android.launcher3.statemanager.StateManager.StateListener; +import com.android.launcher3.views.OptionsPopupView.OptionItem; + +/** + * Placeholder view to expose additional Launcher actions via accessibility actions + */ +public class AccessibilityActionsView extends View implements StateListener { + + public AccessibilityActionsView(Context context) { + this(context, null); + } + + public AccessibilityActionsView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public AccessibilityActionsView(Context context, @Nullable AttributeSet attrs, + int defStyleAttr) { + super(context, attrs, defStyleAttr); + Launcher.getLauncher(context).getStateManager().addStateListener(this); + setWillNotDraw(true); + } + + @Override + public void onStateTransitionComplete(LauncherState finalState) { + setImportantForAccessibility(finalState == NORMAL + ? IMPORTANT_FOR_ACCESSIBILITY_YES : IMPORTANT_FOR_ACCESSIBILITY_NO); + } + + @Override + public AccessibilityNodeInfo createAccessibilityNodeInfo() { + AccessibilityNodeInfo info = super.createAccessibilityNodeInfo(); + Launcher l = Launcher.getLauncher(getContext()); + info.addAction(new AccessibilityAction( + R.string.all_apps_button_label, l.getText(R.string.all_apps_button_label))); + for (OptionItem item : OptionsPopupView.getOptions(l)) { + info.addAction(new AccessibilityAction(item.labelRes, l.getText(item.labelRes))); + } + return info; + } + + @Override + public boolean performAccessibilityAction(int action, Bundle arguments) { + if (super.performAccessibilityAction(action, arguments)) { + return true; + } + Launcher l = Launcher.getLauncher(getContext()); + if (action == R.string.all_apps_button_label) { + l.getStateManager().goToState(ALL_APPS); + return true; + } + for (OptionItem item : OptionsPopupView.getOptions(l)) { + if (item.labelRes == action) { + if (item.eventId.getId() > 0) { + l.getStatsLogManager().logger().log(item.eventId); + } + if (item.clickListener.onLongClick(this)) { + return true; + } + } + } + return false; + } +} diff --git a/src/com/android/launcher3/views/OptionsPopupView.java b/src/com/android/launcher3/views/OptionsPopupView.java index 049a1acbf3..e95dc5b83f 100644 --- a/src/com/android/launcher3/views/OptionsPopupView.java +++ b/src/com/android/launcher3/views/OptionsPopupView.java @@ -85,10 +85,10 @@ public class OptionsPopupView extends ArrowPopup if (item == null) { return false; } - if (item.mEventId.getId() > 0) { - mLauncher.getStatsLogManager().logger().log(item.mEventId); + if (item.eventId.getId() > 0) { + mLauncher.getStatsLogManager().logger().log(item.eventId); } - if (item.mClickListener.onLongClick(view)) { + if (item.clickListener.onLongClick(view)) { close(true); return true; } @@ -130,8 +130,8 @@ public class OptionsPopupView extends ArrowPopup for (OptionItem item : items) { DeepShortcutView view = (DeepShortcutView) popup.inflateAndAdd(R.layout.system_shortcut, popup); - view.getIconView().setBackgroundResource(item.mIconRes); - view.getBubbleText().setText(item.mLabelRes); + view.getIconView().setBackgroundResource(item.iconRes); + view.getBubbleText().setText(item.labelRes); view.setDividerVisibility(View.INVISIBLE); view.setOnClickListener(popup); view.setOnLongClickListener(popup); @@ -152,7 +152,13 @@ public class OptionsPopupView extends ArrowPopup y = launcher.getDragLayer().getHeight() / 2; } RectF target = new RectF(x - halfSize, y - halfSize, x + halfSize, y + halfSize); + show(launcher, target, getOptions(launcher)); + } + /** + * Returns the list of supported actions + */ + public static ArrayList getOptions(Launcher launcher) { ArrayList options = new ArrayList<>(); int resString = Utilities.existsStyleWallpapers(launcher) ? R.string.styles_wallpaper_button_text : R.string.wallpaper_button_text; @@ -170,10 +176,10 @@ public class OptionsPopupView extends ArrowPopup LAUNCHER_SETTINGS_BUTTON_TAP_OR_LONGPRESS, OptionsPopupView::startSettings)); - show(launcher, target, options); + return options; } - public static boolean onWidgetsClicked(View view) { + private static boolean onWidgetsClicked(View view) { return openWidgets(Launcher.getLauncher(view.getContext())) != null; } @@ -188,7 +194,7 @@ public class OptionsPopupView extends ArrowPopup } } - public static boolean startSettings(View view) { + private static boolean startSettings(View view) { TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "start: startSettings"); Launcher launcher = Launcher.getLauncher(view.getContext()); launcher.startActivity(new Intent(Intent.ACTION_APPLICATION_PREFERENCES) @@ -201,7 +207,7 @@ public class OptionsPopupView extends ArrowPopup * Event handler for the wallpaper picker button that appears after a long press * on the home screen. */ - public static boolean startWallpaperPicker(View v) { + private static boolean startWallpaperPicker(View v) { Launcher launcher = Launcher.getLauncher(v.getContext()); if (!Utilities.isWallpaperAllowed(launcher)) { Toast.makeText(launcher, R.string.msg_disabled_by_admin, Toast.LENGTH_SHORT).show(); @@ -233,17 +239,17 @@ public class OptionsPopupView extends ArrowPopup public static class OptionItem { - private final int mLabelRes; - private final int mIconRes; - private final EventEnum mEventId; - private final OnLongClickListener mClickListener; + public final int labelRes; + public final int iconRes; + public final EventEnum eventId; + public final OnLongClickListener clickListener; public OptionItem(int labelRes, int iconRes, EventEnum eventId, OnLongClickListener clickListener) { - mLabelRes = labelRes; - mIconRes = iconRes; - mEventId = eventId; - mClickListener = clickListener; + this.labelRes = labelRes; + this.iconRes = iconRes; + this.eventId = eventId; + this.clickListener = clickListener; } } } diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java index 22faf97cc4..7f0765becd 100644 --- a/src/com/android/launcher3/views/ScrimView.java +++ b/src/com/android/launcher3/views/ScrimView.java @@ -15,119 +15,37 @@ */ package com.android.launcher3.views; -import static android.content.Context.ACCESSIBILITY_SERVICE; -import static android.view.MotionEvent.ACTION_DOWN; - import static androidx.core.graphics.ColorUtils.compositeColors; -import static com.android.launcher3.LauncherState.ALL_APPS; -import static com.android.launcher3.LauncherState.NORMAL; -import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; -import static com.android.launcher3.anim.Interpolators.DEACCEL; -import static com.android.launcher3.anim.Interpolators.LINEAR; -import static com.android.launcher3.anim.Interpolators.clampToProgress; import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound; import static com.android.launcher3.util.SystemUiController.UI_STATE_SCRIM_VIEW; -import android.animation.Animator; -import android.animation.AnimatorListenerAdapter; -import android.animation.Keyframe; -import android.animation.ObjectAnimator; -import android.animation.PropertyValuesHolder; -import android.animation.RectEvaluator; import android.content.Context; -import android.content.res.Resources; import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Point; import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.os.Bundle; import android.util.AttributeSet; -import android.util.IntProperty; -import android.view.KeyEvent; -import android.view.MotionEvent; import android.view.View; -import android.view.accessibility.AccessibilityManager; -import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.core.graphics.ColorUtils; -import androidx.core.view.ViewCompat; -import androidx.core.view.accessibility.AccessibilityNodeInfoCompat; -import androidx.core.view.accessibility.AccessibilityNodeInfoCompat.AccessibilityActionCompat; -import androidx.customview.widget.ExploreByTouchHelper; -import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherState; import com.android.launcher3.R; -import com.android.launcher3.Utilities; -import com.android.launcher3.statemanager.StateManager; -import com.android.launcher3.statemanager.StateManager.StateListener; import com.android.launcher3.uioverrides.WallpaperColorInfo; import com.android.launcher3.uioverrides.WallpaperColorInfo.OnChangeListener; -import com.android.launcher3.userevent.nano.LauncherLogProto.Action; -import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType; -import com.android.launcher3.util.MultiValueAlpha; -import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.Themes; -import com.android.launcher3.widget.WidgetsFullSheet; - -import java.util.List; /** * Simple scrim which draws a flat color */ -public class ScrimView extends View implements Insettable, OnChangeListener, - AccessibilityStateChangeListener { - - public static final IntProperty DRAG_HANDLE_ALPHA = - new IntProperty("dragHandleAlpha") { - - @Override - public Integer get(ScrimView scrimView) { - return scrimView.mDragHandleAlpha; - } - - @Override - public void setValue(ScrimView scrimView, int value) { - scrimView.setDragHandleAlpha(value); - } - }; - private static final int WALLPAPERS = R.string.wallpaper_button_text; - private static final int WIDGETS = R.string.widget_button_text; - private static final int SETTINGS = R.string.settings_button_text; - private static final int ALPHA_CHANNEL_COUNT = 1; - - private static final long DRAG_HANDLE_BOUNCE_DURATION_MS = 300; - // How much to delay before repeating the bounce. - private static final long DRAG_HANDLE_BOUNCE_DELAY_MS = 200; - // Repeat this many times (i.e. total number of bounces is 1 + this). - private static final int DRAG_HANDLE_BOUNCE_REPEAT_COUNT = 2; - - private final Rect mTempRect = new Rect(); - private final int[] mTempPos = new int[2]; +public class ScrimView extends View implements Insettable, OnChangeListener { protected final T mLauncher; private final WallpaperColorInfo mWallpaperColorInfo; - private final AccessibilityManager mAM; protected final int mEndScrim; protected final boolean mIsScrimDark; - private final StateListener mAccessibilityLauncherStateListener = - new StateListener() { - @Override - public void onStateTransitionComplete(LauncherState finalState) { - setImportantForAccessibility(finalState == ALL_APPS - ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS - : IMPORTANT_FOR_ACCESSIBILITY_AUTO); - } - }; - protected float mMaxScrimAlpha; protected float mProgress = 1; @@ -137,22 +55,6 @@ public class ScrimView extends View implements Insettable, O protected int mEndFlatColor; protected int mEndFlatColorAlpha; - protected final Point mDragHandleSize; - private final int mDragHandleTouchSize; - private final int mDragHandlePaddingInVerticalBarLayout; - protected float mDragHandleOffset; - private final Rect mDragHandleBounds; - private final RectF mHitRect = new RectF(); - private ObjectAnimator mDragHandleAnim; - - private final MultiValueAlpha mMultiValueAlpha; - - private final AccessibilityHelper mAccessibilityHelper; - @Nullable - protected Drawable mDragHandle; - - private int mDragHandleAlpha = 255; - public ScrimView(Context context, AttributeSet attrs) { super(context, attrs); mLauncher = Launcher.cast(Launcher.getLauncher(context)); @@ -161,59 +63,24 @@ public class ScrimView extends View implements Insettable, O mIsScrimDark = ColorUtils.calculateLuminance(mEndScrim) < 0.5f; mMaxScrimAlpha = 0.7f; - - Resources res = context.getResources(); - mDragHandleSize = new Point(res.getDimensionPixelSize(R.dimen.vertical_drag_handle_width), - res.getDimensionPixelSize(R.dimen.vertical_drag_handle_height)); - mDragHandleBounds = new Rect(0, 0, mDragHandleSize.x, mDragHandleSize.y); - mDragHandleTouchSize = res.getDimensionPixelSize(R.dimen.vertical_drag_handle_touch_size); - mDragHandlePaddingInVerticalBarLayout = context.getResources() - .getDimensionPixelSize(R.dimen.vertical_drag_handle_padding_in_vertical_bar_layout); - - mAccessibilityHelper = createAccessibilityHelper(); - ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper); - - mAM = (AccessibilityManager) context.getSystemService(ACCESSIBILITY_SERVICE); setFocusable(false); - mMultiValueAlpha = new MultiValueAlpha(this, ALPHA_CHANNEL_COUNT); - } - - public AlphaProperty getAlphaProperty(int index) { - return mMultiValueAlpha.getProperty(index); - } - - @NonNull - protected AccessibilityHelper createAccessibilityHelper() { - return new AccessibilityHelper(); } @Override - public void setInsets(Rect insets) { - updateDragHandleBounds(); - updateDragHandleVisibility(); - } + public void setInsets(Rect insets) { } - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - updateDragHandleBounds(); - } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); mWallpaperColorInfo.addOnChangeListener(this); onExtractedColorsChanged(mWallpaperColorInfo); - - mAM.addAccessibilityStateChangeListener(this); - onAccessibilityStateChanged(mAM.isEnabled()); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mWallpaperColorInfo.removeOnChangeListener(this); - mAM.removeAccessibilityStateChangeListener(this); } @Override @@ -234,10 +101,8 @@ public class ScrimView extends View implements Insettable, O public void setProgress(float progress) { if (mProgress != progress) { mProgress = progress; - stopDragHandleEducationAnim(); updateColors(); updateSysUiColors(); - updateDragHandleAlpha(); invalidate(); } } @@ -260,286 +125,10 @@ public class ScrimView extends View implements Insettable, O } } - protected void updateDragHandleAlpha() { - if (mDragHandle != null) { - mDragHandle.setAlpha(mDragHandleAlpha); - } - } - - private void setDragHandleAlpha(int alpha) { - if (alpha != mDragHandleAlpha) { - mDragHandleAlpha = alpha; - if (mDragHandle != null) { - mDragHandle.setAlpha(mDragHandleAlpha); - invalidate(); - } - } - } - @Override protected void onDraw(Canvas canvas) { if (mCurrentFlatColor != 0) { canvas.drawColor(mCurrentFlatColor); } - drawDragHandle(canvas); - } - - protected void drawDragHandle(Canvas canvas) { - if (mDragHandle != null) { - canvas.translate(0, -mDragHandleOffset); - mDragHandle.draw(canvas); - canvas.translate(0, mDragHandleOffset); - } - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - boolean superHandledTouch = super.onTouchEvent(event); - if (event.getAction() == ACTION_DOWN) { - if (!superHandledTouch && mHitRect.contains(event.getX(), event.getY())) { - if (startDragHandleEducationAnim()) { - return true; - } - } - stopDragHandleEducationAnim(); - } - return superHandledTouch; - } - - /** - * Animates the drag handle to demonstrate how to get to all apps. - * @return Whether the animation was started (false if drag handle is invisible). - */ - public boolean startDragHandleEducationAnim() { - stopDragHandleEducationAnim(); - - if (mDragHandle == null || mDragHandle.getAlpha() != 255) { - return false; - } - - final Drawable drawable = mDragHandle; - mDragHandle = null; - - Rect bounds = new Rect(mDragHandleBounds); - bounds.offset(0, -(int) mDragHandleOffset); - drawable.setBounds(bounds); - - Rect topBounds = new Rect(bounds); - topBounds.offset(0, -bounds.height()); - - Rect invalidateRegion = new Rect(bounds); - invalidateRegion.top = topBounds.top; - - final float progressToReachTop = 0.6f; - Keyframe frameTop = Keyframe.ofObject(progressToReachTop, topBounds); - frameTop.setInterpolator(DEACCEL); - Keyframe frameBot = Keyframe.ofObject(1, bounds); - frameBot.setInterpolator(ACCEL_DEACCEL); - PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("bounds", - Keyframe.ofObject(0, bounds), frameTop, frameBot); - holder.setEvaluator(new RectEvaluator()); - - mDragHandleAnim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder); - long totalBounceDuration = DRAG_HANDLE_BOUNCE_DURATION_MS + DRAG_HANDLE_BOUNCE_DELAY_MS; - // The bounce finishes by this progress, the rest of the duration just delays next bounce. - float delayStartProgress = 1f - (float) DRAG_HANDLE_BOUNCE_DELAY_MS / totalBounceDuration; - mDragHandleAnim.addUpdateListener((v) -> invalidate(invalidateRegion)); - mDragHandleAnim.setDuration(totalBounceDuration); - mDragHandleAnim.setInterpolator(clampToProgress(LINEAR, 0, delayStartProgress)); - mDragHandleAnim.setRepeatCount(DRAG_HANDLE_BOUNCE_REPEAT_COUNT); - getOverlay().add(drawable); - - mDragHandleAnim.addListener(new AnimatorListenerAdapter() { - @Override - public void onAnimationEnd(Animator animation) { - mDragHandleAnim = null; - getOverlay().remove(drawable); - updateDragHandleVisibility(drawable); - } - }); - mDragHandleAnim.start(); - return true; - } - - private void stopDragHandleEducationAnim() { - if (mDragHandleAnim != null) { - mDragHandleAnim.end(); - } - } - - protected void updateDragHandleBounds() { - DeviceProfile grid = mLauncher.getDeviceProfile(); - final int left; - final int width = getMeasuredWidth(); - final int top = getMeasuredHeight() - mDragHandleSize.y - grid.getInsets().bottom; - final int topMargin; - - if (grid.isVerticalBarLayout()) { - topMargin = grid.workspacePadding.bottom + mDragHandlePaddingInVerticalBarLayout; - if (grid.isSeascape()) { - left = width - grid.getInsets().right - mDragHandleSize.x - - mDragHandlePaddingInVerticalBarLayout; - } else { - left = grid.getInsets().left + mDragHandlePaddingInVerticalBarLayout; - } - } else { - left = Math.round((width - mDragHandleSize.x) / 2f); - topMargin = grid.hotseatBarSizePx; - } - mDragHandleBounds.offsetTo(left, top - topMargin); - mHitRect.set(mDragHandleBounds); - // Inset outwards to increase touch size. - mHitRect.inset((mDragHandleSize.x - mDragHandleTouchSize) / 2f, - (mDragHandleSize.y - mDragHandleTouchSize) / 2f); - - if (mDragHandle != null) { - mDragHandle.setBounds(mDragHandleBounds); - } - } - - @Override - public void onAccessibilityStateChanged(boolean enabled) { - StateManager stateManager = mLauncher.getStateManager(); - stateManager.removeStateListener(mAccessibilityLauncherStateListener); - - if (enabled) { - stateManager.addStateListener(mAccessibilityLauncherStateListener); - mAccessibilityLauncherStateListener.onStateTransitionComplete(stateManager.getState()); - } else { - setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); - } - updateDragHandleVisibility(); - } - - public void updateDragHandleVisibility() { - updateDragHandleVisibility(null); - } - - private void updateDragHandleVisibility(@Nullable Drawable recycle) { - boolean visible = shouldDragHandleBeVisible(); - boolean wasVisible = mDragHandle != null; - if (visible != wasVisible) { - if (visible) { - mDragHandle = recycle != null ? recycle : - mLauncher.getDrawable(R.drawable.drag_handle_indicator_shadow); - mDragHandle.setBounds(mDragHandleBounds); - - updateDragHandleAlpha(); - } else { - mDragHandle = null; - } - invalidate(); - } - } - - protected boolean shouldDragHandleBeVisible() { - return mLauncher.getDeviceProfile().isVerticalBarLayout() || mAM.isEnabled(); - } - - @Override - public boolean dispatchHoverEvent(MotionEvent event) { - return mAccessibilityHelper.dispatchHoverEvent(event) || super.dispatchHoverEvent(event); - } - - @Override - public boolean dispatchKeyEvent(KeyEvent event) { - return mAccessibilityHelper.dispatchKeyEvent(event) || super.dispatchKeyEvent(event); - } - - @Override - public void onFocusChanged(boolean gainFocus, int direction, - Rect previouslyFocusedRect) { - super.onFocusChanged(gainFocus, direction, previouslyFocusedRect); - mAccessibilityHelper.onFocusChanged(gainFocus, direction, previouslyFocusedRect); - } - - protected class AccessibilityHelper extends ExploreByTouchHelper { - - private static final int DRAG_HANDLE_ID = 1; - - public AccessibilityHelper() { - super(ScrimView.this); - } - - @Override - protected int getVirtualViewAt(float x, float y) { - return mHitRect.contains((int) x, (int) y) - ? DRAG_HANDLE_ID : INVALID_ID; - } - - @Override - protected void getVisibleVirtualViews(List virtualViewIds) { - virtualViewIds.add(DRAG_HANDLE_ID); - } - - @Override - protected void onPopulateNodeForVirtualView(int virtualViewId, - AccessibilityNodeInfoCompat node) { - node.setContentDescription(getContext().getString(R.string.all_apps_button_label)); - node.setBoundsInParent(mDragHandleBounds); - - getLocationOnScreen(mTempPos); - mTempRect.set(mDragHandleBounds); - mTempRect.offset(mTempPos[0], mTempPos[1]); - node.setBoundsInScreen(mTempRect); - - node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK); - node.setClickable(true); - node.setFocusable(true); - - if (mLauncher.isInState(NORMAL)) { - Context context = getContext(); - if (Utilities.isWallpaperAllowed(context)) { - node.addAction( - new AccessibilityActionCompat(WALLPAPERS, context.getText(WALLPAPERS))); - } - node.addAction(new AccessibilityActionCompat(WIDGETS, context.getText(WIDGETS))); - node.addAction(new AccessibilityActionCompat(SETTINGS, context.getText(SETTINGS))); - } - } - - @Override - protected boolean onPerformActionForVirtualView( - int virtualViewId, int action, Bundle arguments) { - if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) { - mLauncher.getUserEventDispatcher().logActionOnControl( - Action.Touch.TAP, ControlType.ALL_APPS_BUTTON, - mLauncher.getStateManager().getState().containerType); - mLauncher.getStateManager().goToState(ALL_APPS); - return true; - } else if (action == WALLPAPERS) { - return OptionsPopupView.startWallpaperPicker(ScrimView.this); - } else if (action == WIDGETS) { - int originalImportanceForAccessibility = getImportantForAccessibility(); - setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS); - WidgetsFullSheet widgetsFullSheet = OptionsPopupView.openWidgets(mLauncher); - if (widgetsFullSheet == null) { - setImportantForAccessibility(originalImportanceForAccessibility); - return false; - } - widgetsFullSheet.addOnAttachStateChangeListener(new OnAttachStateChangeListener() { - @Override - public void onViewAttachedToWindow(View view) {} - - @Override - public void onViewDetachedFromWindow(View view) { - setImportantForAccessibility(originalImportanceForAccessibility); - widgetsFullSheet.removeOnAttachStateChangeListener(this); - } - }); - return true; - } else if (action == SETTINGS) { - return OptionsPopupView.startSettings(ScrimView.this); - } - - return false; - } - } - - /** - * @return The top of this scrim view, or {@link Float#MAX_VALUE} if there's no distinct top. - */ - public float getVisualTop() { - return Float.MAX_VALUE; } }