Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ac02319 authored by Tony Wickham's avatar Tony Wickham Committed by Android (Google) Code Review
Browse files

Merge "Initial commit of taskbar stashing" into sc-v2-dev

parents 222a3153 3fd22847
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
-->
<com.android.launcher3.taskbar.TaskbarDragLayer
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/taskbar_container"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
@@ -39,6 +40,7 @@
            android:id="@+id/start_nav_buttons"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            android:paddingLeft="@dimen/taskbar_nav_buttons_spacing"
            android:paddingRight="@dimen/taskbar_nav_buttons_spacing"
            android:gravity="center_vertical"
@@ -54,4 +56,14 @@
            android:layout_gravity="end"/>
    </FrameLayout>

    <View
        android:id="@+id/stashed_handle"
        tools:comment1="The actual size and shape will be set as a ViewOutlineProvider at runtime"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:comment2="TODO: Tint dynamically"
        android:background="?android:attr/textColorPrimary"
        android:clipToOutline="true"
        android:layout_gravity="bottom"/>

</com.android.launcher3.taskbar.TaskbarDragLayer>
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
@@ -153,4 +153,7 @@
    <dimen name="taskbar_folder_margin">16dp</dimen>
    <dimen name="taskbar_nav_buttons_spacing">16dp</dimen>
    <dimen name="taskbar_nav_buttons_size">48dp</dimen>
    <dimen name="taskbar_stashed_size">24dp</dimen>
    <dimen name="taskbar_stashed_handle_width">220dp</dimen>
    <dimen name="taskbar_stashed_handle_height">6dp</dimen>
</resources>
+50 −25
Original line number Diff line number Diff line
@@ -50,21 +50,23 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
    private final TaskbarHotseatController mHotseatController;

    private final TaskbarActivityContext mContext;
    final TaskbarDragLayer mTaskbarDragLayer;
    final TaskbarView mTaskbarView;
    private final TaskbarDragLayer mTaskbarDragLayer;
    private final TaskbarView mTaskbarView;

    private final AnimatedFloat mIconAlignmentForResumedState =
            new AnimatedFloat(this::onIconAlignmentRatioChanged);
    private final AnimatedFloat mIconAlignmentForGestureState =
            new AnimatedFloat(this::onIconAlignmentRatioChanged);

    // Initialized in init.
    private TaskbarControllers mControllers;
    private AnimatedFloat mTaskbarBackgroundAlpha;
    private AlphaProperty mIconAlphaForHome;
    private boolean mIsAnimatingToLauncher;
    private boolean mIsAnimatingToLauncherViaResume;
    private boolean mIsAnimatingToLauncherViaGesture;
    private TaskbarKeyguardController mKeyguardController;

    private LauncherState mTargetStateOverride = null;
    private TaskbarControllers mControllers;

    public LauncherTaskbarUIController(
            BaseQuickstepLauncher launcher, TaskbarActivityContext context) {
@@ -80,12 +82,13 @@ public class LauncherTaskbarUIController extends TaskbarUIController {

    @Override
    protected void init(TaskbarControllers taskbarControllers) {
        mTaskbarBackgroundAlpha = taskbarControllers.taskbarDragLayerController
        mControllers = taskbarControllers;

        mTaskbarBackgroundAlpha = mControllers.taskbarDragLayerController
                .getTaskbarBackgroundAlpha();
        MultiValueAlpha taskbarIconAlpha = taskbarControllers.taskbarViewController
                .getTaskbarIconAlpha();

        MultiValueAlpha taskbarIconAlpha = mControllers.taskbarViewController.getTaskbarIconAlpha();
        mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
        mControllers = taskbarControllers;

        mHotseatController.init();
        mLauncher.setTaskbarUIController(this);
@@ -109,19 +112,17 @@ public class LauncherTaskbarUIController extends TaskbarUIController {

    @Override
    protected boolean isTaskbarTouchable() {
        return !mIsAnimatingToLauncher && mTargetStateOverride == null;
        return !isAnimatingToLauncher() && !mControllers.taskbarStashController.isStashed();
    }

    private boolean isAnimatingToLauncher() {
        return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
    }

    @Override
    protected void updateContentInsets(Rect outContentInsets) {
        // TaskbarDragLayer provides insets to other apps based on contentInsets. These
        // insets should stay consistent even if we expand TaskbarDragLayer's bounds, e.g.
        // to show a floating view like Folder. Thus, we set the contentInsets to be where
        // mTaskbarView is, since its position never changes and insets rather than overlays.
        outContentInsets.left = mTaskbarView.getLeft();
        outContentInsets.top = mTaskbarView.getTop();
        outContentInsets.right = mTaskbarDragLayer.getWidth() - mTaskbarView.getRight();
        outContentInsets.bottom = mTaskbarDragLayer.getHeight() - mTaskbarView.getBottom();
        int contentHeight = mControllers.taskbarStashController.getContentHeight();
        outContentInsets.top = mTaskbarDragLayer.getHeight() - contentHeight;
    }

    /**
@@ -137,13 +138,20 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
            }
        }

        long duration = QuickstepTransitionManager.CONTENT_ALPHA_DURATION;
        ObjectAnimator anim = mIconAlignmentForResumedState.animateToValue(
                getCurrentIconAlignmentRatio(), isResumed ? 1 : 0)
                .setDuration(QuickstepTransitionManager.CONTENT_ALPHA_DURATION);
                .setDuration(duration);

        anim.addListener(AnimatorListeners.forEndCallback(() -> mIsAnimatingToLauncher = false));
        anim.addListener(AnimatorListeners.forEndCallback(
                () -> mIsAnimatingToLauncherViaResume = false));
        anim.start();
        mIsAnimatingToLauncher = isResumed;
        mIsAnimatingToLauncherViaResume = isResumed;

        if (!isResumed) {
            TaskbarStashController stashController = mControllers.taskbarStashController;
            stashController.animateToIsStashed(stashController.isStashedInApp(), duration);
        }
    }

    /**
@@ -155,36 +163,48 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
    public Animator createAnimToLauncher(@NonNull LauncherState toState,
            @NonNull RecentsAnimationCallbacks callbacks,
            long duration) {
        TaskbarStashController stashController = mControllers.taskbarStashController;
        ObjectAnimator animator = mIconAlignmentForGestureState
                .animateToValue(mIconAlignmentForGestureState.value, 1)
                .animateToValue(1)
                .setDuration(duration);
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mTargetStateOverride = null;
                animator.removeListener(this);
            }

            @Override
            public void onAnimationStart(Animator animation) {
                mTargetStateOverride = toState;
                mIsAnimatingToLauncherViaGesture = true;
                // TODO: base this on launcher state
                stashController.animateToIsStashed(false, duration);
            }
        });
        callbacks.addListener(new RecentsAnimationListener() {
            @Override
            public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
                endGestureStateOverride();
                endGestureStateOverride(true);
            }

            @Override
            public void onRecentsAnimationFinished(RecentsAnimationController controller) {
                endGestureStateOverride();
                endGestureStateOverride(!controller.getFinishTargetIsLauncher());
            }

            private void endGestureStateOverride() {
            private void endGestureStateOverride(boolean finishedToApp) {
                callbacks.removeListener(this);
                mIsAnimatingToLauncherViaGesture = false;

                mIconAlignmentForGestureState
                        .animateToValue(mIconAlignmentForGestureState.value, 0)
                        .animateToValue(0)
                        .start();

                if (finishedToApp) {
                    // We only need this for the exiting live tile case.
                    stashController.animateToIsStashed(stashController.isStashedInApp());
                }
            }
        });
        return animator;
@@ -215,6 +235,11 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
        }
    }

    @Override
    public boolean onLongPressToUnstashTaskbar() {
        return mControllers.taskbarStashController.onLongPressToUnstashTaskbar();
    }

    /**
     * Should be called when one or more items in the Hotseat have changed.
     */
+108 −0
Original line number Diff line number Diff line
/*
 * 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.content.res.Resources;
import android.graphics.Outline;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewOutlineProvider;

import androidx.annotation.Nullable;

import com.android.launcher3.R;
import com.android.launcher3.anim.RevealOutlineAnimation;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.quickstep.AnimatedFloat;

/**
 * Handles properties/data collection, then passes the results to our stashed handle View to render.
 */
public class StashedHandleViewController {

    private final TaskbarActivityContext mActivity;
    private final View mStashedHandleView;
    private final int mStashedHandleWidth;
    private final int mStashedHandleHeight;
    private final AnimatedFloat mTaskbarStashedHandleAlpha = new AnimatedFloat(
            this::updateStashedHandleAlpha);

    // 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;

    private boolean mIsAtStashedRevealBounds = true;

    public StashedHandleViewController(TaskbarActivityContext activity, View stashedHandleView) {
        mActivity = activity;
        mStashedHandleView = stashedHandleView;
        final Resources resources = mActivity.getResources();
        mStashedHandleWidth = resources.getDimensionPixelSize(R.dimen.taskbar_stashed_handle_width);
        mStashedHandleHeight = resources.getDimensionPixelSize(
                R.dimen.taskbar_stashed_handle_height);
    }

    public void init(TaskbarControllers controllers) {
        mControllers = controllers;
        mStashedHandleView.getLayoutParams().height = mActivity.getDeviceProfile().taskbarSize;

        updateStashedHandleAlpha();

        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);
                mStashedHandleRadius = view.getHeight() / 2f;
                outline.setRoundRect(mStashedHandleBounds, mStashedHandleRadius);
            }
        });
    }

    public AnimatedFloat getStashedHandleAlpha() {
        return mTaskbarStashedHandleAlpha;
    }

    /**
     * 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 @Nullable Animator createRevealAnimToIsStashed(boolean isStashed) {
        if (mIsAtStashedRevealBounds == isStashed) {
            return null;
        }
        mIsAtStashedRevealBounds = isStashed;
        final RevealOutlineAnimation handleRevealProvider = new RoundedRectRevealOutlineProvider(
                mStashedHandleRadius, mStashedHandleRadius,
                mControllers.taskbarViewController.getIconLayoutBounds(), mStashedHandleBounds);
        return handleRevealProvider.createRevealAnimator(mStashedHandleView, !isStashed);
    }

    protected void updateStashedHandleAlpha() {
        mStashedHandleView.setAlpha(mTaskbarStashedHandleAlpha.value);
    }
}
+4 −1
Original line number Diff line number Diff line
@@ -115,6 +115,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
                R.layout.taskbar, null, false);
        TaskbarView taskbarView = mDragLayer.findViewById(R.id.taskbar_view);
        FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
        View stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);

        // Construct controllers.
        mControllers = new TaskbarControllers(this,
@@ -125,7 +126,9 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
                        R.color.popup_color_primary_light),
                new TaskbarDragLayerController(this, mDragLayer),
                new TaskbarViewController(this, taskbarView),
                new TaskbarKeyguardController(this));
                new TaskbarKeyguardController(this),
                new StashedHandleViewController(this, stashedHandleView),
                new TaskbarStashController(this));

        Display display = windowContext.getDisplay();
        Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
Loading