diff options
Diffstat (limited to 'quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java')
-rw-r--r-- | quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java | 203 |
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; + } +} |