summaryrefslogtreecommitdiff
path: root/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
diff options
context:
space:
mode:
Diffstat (limited to 'quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java')
-rw-r--r--quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java203
1 files changed, 203 insertions, 0 deletions
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
new file mode 100644
index 0000000000..22ca63f963
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -0,0 +1,203 @@
+/*
+ * 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 android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewOutlineProvider;
+
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.anim.RevealOutlineAnimation;
+import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.util.Executors;
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.quickstep.AnimatedFloat;
+import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
+
+/**
+ * Handles properties/data collection, then passes the results to our stashed handle View to render.
+ */
+public class StashedHandleViewController {
+
+ public static final int ALPHA_INDEX_STASHED = 0;
+ public static final int ALPHA_INDEX_HOME_DISABLED = 1;
+ private static final int NUM_ALPHA_CHANNELS = 2;
+
+ /**
+ * The SharedPreferences key for whether the stashed handle region is dark.
+ */
+ private static final String SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY =
+ "stashed_handle_region_is_dark";
+
+ private final TaskbarActivityContext mActivity;
+ private final SharedPreferences mPrefs;
+ private final StashedHandleView mStashedHandleView;
+ private final int mStashedHandleWidth;
+ private final int mStashedHandleHeight;
+ private final RegionSamplingHelper mRegionSamplingHelper;
+ private final MultiValueAlpha mTaskbarStashedHandleAlpha;
+ private final AnimatedFloat mTaskbarStashedHandleHintScale = new AnimatedFloat(
+ this::updateStashedHandleHintScale);
+
+ // Initialized in init.
+ private TaskbarControllers mControllers;
+
+ // The bounds we want to clip to in the settled state when showing the stashed handle.
+ private final Rect mStashedHandleBounds = new Rect();
+ private float mStashedHandleRadius;
+
+ // When the reveal animation is cancelled, we can assume it's about to create a new animation,
+ // which should start off at the same point the cancelled one left off.
+ private float mStartProgressForNextRevealAnim;
+ private boolean mWasLastRevealAnimReversed;
+
+ public StashedHandleViewController(TaskbarActivityContext activity,
+ StashedHandleView stashedHandleView) {
+ mActivity = activity;
+ mPrefs = Utilities.getPrefs(mActivity);
+ mStashedHandleView = stashedHandleView;
+ mTaskbarStashedHandleAlpha = new MultiValueAlpha(mStashedHandleView, NUM_ALPHA_CHANNELS);
+ mTaskbarStashedHandleAlpha.setUpdateVisibility(true);
+ mStashedHandleView.updateHandleColor(
+ mPrefs.getBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY, false),
+ false /* animate */);
+ final Resources resources = mActivity.getResources();
+ mStashedHandleWidth = resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width);
+ mStashedHandleHeight = resources.getDimensionPixelSize(
+ R.dimen.taskbar_stashed_handle_height);
+ mRegionSamplingHelper = new RegionSamplingHelper(mStashedHandleView,
+ new RegionSamplingHelper.SamplingCallback() {
+ @Override
+ public void onRegionDarknessChanged(boolean isRegionDark) {
+ mStashedHandleView.updateHandleColor(isRegionDark, true /* animate */);
+ mPrefs.edit().putBoolean(SHARED_PREFS_STASHED_HANDLE_REGION_DARK_KEY,
+ isRegionDark).apply();
+ }
+
+ @Override
+ public Rect getSampledRegion(View sampledView) {
+ return mStashedHandleView.getSampledRegion();
+ }
+ }, Executors.UI_HELPER_EXECUTOR);
+ }
+
+ public void init(TaskbarControllers controllers) {
+ mControllers = controllers;
+ mStashedHandleView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;
+
+ mTaskbarStashedHandleAlpha.getProperty(ALPHA_INDEX_STASHED).setValue(0);
+ mTaskbarStashedHandleHintScale.updateValue(1f);
+
+ final int stashedTaskbarHeight = mControllers.taskbarStashController.getStashedHeight();
+ mStashedHandleView.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ final int stashedCenterX = view.getWidth() / 2;
+ final int stashedCenterY = view.getHeight() - stashedTaskbarHeight / 2;
+ mStashedHandleBounds.set(
+ stashedCenterX - mStashedHandleWidth / 2,
+ stashedCenterY - mStashedHandleHeight / 2,
+ stashedCenterX + mStashedHandleWidth / 2,
+ stashedCenterY + mStashedHandleHeight / 2);
+ mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
+ mStashedHandleRadius = view.getHeight() / 2f;
+ outline.setRoundRect(mStashedHandleBounds, mStashedHandleRadius);
+ }
+ });
+
+ mStashedHandleView.addOnLayoutChangeListener((view, i, i1, i2, i3, i4, i5, i6, i7) -> {
+ final int stashedCenterX = view.getWidth() / 2;
+ final int stashedCenterY = view.getHeight() - stashedTaskbarHeight / 2;
+
+ view.setPivotX(stashedCenterX);
+ view.setPivotY(stashedCenterY);
+ });
+ }
+
+ public void onDestroy() {
+ mRegionSamplingHelper.stopAndDestroy();
+ }
+
+ public MultiValueAlpha getStashedHandleAlpha() {
+ return mTaskbarStashedHandleAlpha;
+ }
+
+ public AnimatedFloat getStashedHandleHintScale() {
+ return mTaskbarStashedHandleHintScale;
+ }
+
+ /**
+ * Creates and returns a {@link RevealOutlineAnimation} Animator that updates the stashed handle
+ * shape and size. When stashed, the shape is a thin rounded pill. When unstashed, the shape
+ * morphs into the size of where the taskbar icons will be.
+ */
+ public Animator createRevealAnimToIsStashed(boolean isStashed) {
+ final RevealOutlineAnimation handleRevealProvider = new RoundedRectRevealOutlineProvider(
+ mStashedHandleRadius, mStashedHandleRadius,
+ mControllers.taskbarViewController.getIconLayoutBounds(), mStashedHandleBounds);
+
+ boolean isReversed = !isStashed;
+ boolean changingDirection = mWasLastRevealAnimReversed != isReversed;
+ mWasLastRevealAnimReversed = isReversed;
+ if (changingDirection) {
+ mStartProgressForNextRevealAnim = 1f - mStartProgressForNextRevealAnim;
+ }
+
+ ValueAnimator revealAnim = handleRevealProvider.createRevealAnimator(mStashedHandleView,
+ isReversed, mStartProgressForNextRevealAnim);
+ revealAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mStartProgressForNextRevealAnim = ((ValueAnimator) animation).getAnimatedFraction();
+ }
+ });
+ return revealAnim;
+ }
+
+ public void onIsStashed(boolean isStashed) {
+ mRegionSamplingHelper.setWindowVisible(isStashed);
+ if (isStashed) {
+ mStashedHandleView.updateSampledRegion(mStashedHandleBounds);
+ mRegionSamplingHelper.start(mStashedHandleView.getSampledRegion());
+ } else {
+ mRegionSamplingHelper.stop();
+ }
+ }
+
+ protected void updateStashedHandleHintScale() {
+ mStashedHandleView.setScaleX(mTaskbarStashedHandleHintScale.value);
+ mStashedHandleView.setScaleY(mTaskbarStashedHandleHintScale.value);
+ }
+
+ /**
+ * Should be called when the home button is disabled, so we can hide this handle as well.
+ */
+ public void setIsHomeButtonDisabled(boolean homeDisabled) {
+ mTaskbarStashedHandleAlpha.getProperty(ALPHA_INDEX_HOME_DISABLED).setValue(
+ homeDisabled ? 0 : 1);
+ }
+
+ public boolean isStashedHandleVisible() {
+ return mStashedHandleView.getVisibility() == View.VISIBLE;
+ }
+}