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

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

Merge "Animate away Recent Apps section when going to home" into main

parents 6edce2ad 79f3cefa
Loading
Loading
Loading
Loading
+19 −5
Original line number Diff line number Diff line
@@ -108,9 +108,15 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
    private long mAllAppsButtonTouchDelayMs;
    private boolean mAllAppsTouchTriggered;

    // Only non-null when device supports having an All Apps button.
    // Only non-null when device supports having an All Apps button, or Recent Apps.
    private @Nullable IconButtonView mTaskbarDivider;

    /**
     * Whether the divider is between Hotseat icons and Recents,
     * instead of between All Apps button and Hotseat.
     */
    private boolean mAddedDividerForRecents;

    private final View mQsb;

    private final float mTransientTaskbarMinWidth;
@@ -340,7 +346,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
    protected void updateHotseatItems(ItemInfo[] hotseatItemInfos, List<GroupTask> recentTasks) {
        int nextViewIndex = 0;
        int numViewsAnimated = 0;
        boolean addedDividerForRecents = false;
        mAddedDividerForRecents = false;

        if (mAllAppsButton != null) {
            removeView(mAllAppsButton);
@@ -435,7 +441,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar

        if (mTaskbarDivider != null && !recentTasks.isEmpty()) {
            addView(mTaskbarDivider, nextViewIndex++);
            addedDividerForRecents = true;
            mAddedDividerForRecents = true;
        }

        // Add Recent/Running icons.
@@ -499,10 +505,10 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
        }

        if (mAllAppsButton != null) {
            addView(mAllAppsButton, mIsRtl ? getChildCount() : 0);
            addView(mAllAppsButton, mIsRtl ? hotseatItemInfos.length : 0);

            // If there are no recent tasks, add divider after All Apps (unless it's the only view).
            if (!addedDividerForRecents && mTaskbarDivider != null && getChildCount() > 1) {
            if (!mAddedDividerForRecents && mTaskbarDivider != null && getChildCount() > 1) {
                addView(mTaskbarDivider, mIsRtl ? (getChildCount() - 1) : 1);
            }
        }
@@ -733,6 +739,14 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
        return mTaskbarDivider;
    }

    /**
     * Returns whether the divider is between Hotseat icons and Recents,
     * instead of between All Apps button and Hotseat.
     */
    public boolean isDividerForRecents() {
        return mAddedDividerForRecents;
    }

    /**
     * Returns the QSB in the taskbar.
     */
+74 −19
Original line number Diff line number Diff line
@@ -100,6 +100,12 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
    public static final int ALPHA_INDEX_BUBBLE_BAR = 7;
    private static final int NUM_ALPHA_CHANNELS = 8;

    /** Only used for animation purposes, to position the divider between two item indices. */
    public static final float DIVIDER_VIEW_POSITION_OFFSET = 0.5f;

    /** Used if an unexpected edge case is hit in {@link #getPositionInHotseat}. */
    private static final float ERROR_POSITION_IN_HOTSEAT_NOT_FOUND = -100;

    private static boolean sEnableModelLoadingForTests = true;

    private final TaskbarActivityContext mActivity;
@@ -741,17 +747,22 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
                ? mTransientTaskbarDp.taskbarBottomMargin
                : mPersistentTaskbarDp.taskbarBottomMargin;

        int firstRecentTaskIndex = -1;
        for (int i = 0; i < mTaskbarView.getChildCount(); i++) {
            View child = mTaskbarView.getChildAt(i);
            boolean isAllAppsButton = child == mTaskbarView.getAllAppsButtonView();
            boolean isTaskbarDividerView = child == mTaskbarView.getTaskbarDividerView();
            boolean isRecentTask = child.getTag() instanceof GroupTask;
            // TODO(b/343522351): show recents on the home screen.
            final boolean isRecentsInHotseat = false;
            if (!mIsHotseatIconOnTopWhenAligned) {
                // When going to home, the EMPHASIZED interpolator in TaskbarLauncherStateController
                // plays iconAlignment to 1 really fast, therefore moving the fading towards the end
                // to avoid icons disappearing rather than fading out visually.
                setter.setViewAlpha(child, 0, Interpolators.clampToProgress(LINEAR, 0.8f, 1f));
            } else if ((isAllAppsButton && !FeatureFlags.ENABLE_ALL_APPS_BUTTON_IN_HOTSEAT.get())
                    || (isTaskbarDividerView && enableTaskbarPinning())) {
                    || (isTaskbarDividerView && enableTaskbarPinning())
                    || (isRecentTask && !isRecentsInHotseat)) {
                if (!isToHome
                        && mIsHotseatIconOnTopWhenAligned
                        && mIsStashed) {
@@ -812,25 +823,17 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
                continue;
            }

            float positionInHotseat;
            if (isAllAppsButton) {
                // Note that there is no All Apps button in the hotseat,
                // this position is only used as its convenient for animation purposes.
                positionInHotseat = Utilities.isRtl(child.getResources())
                        ? taskbarDp.numShownHotseatIcons
                        : -1;
            }  else if (isTaskbarDividerView) {
                // Note that there is no taskbar divider view in the hotseat,
                // this position is only used as its convenient for animation purposes.
                positionInHotseat = Utilities.isRtl(child.getResources())
                        ? taskbarDp.numShownHotseatIcons - 0.5f
                        : -0.5f;
            } else if (child.getTag() instanceof ItemInfo) {
                positionInHotseat = ((ItemInfo) child.getTag()).screenId;
            } else {
                Log.w(TAG, "Unsupported view found in createIconAlignmentController, v=" + child);
                continue;
            int recentTaskIndex = -1;
            if (isRecentTask) {
                if (firstRecentTaskIndex < 0) {
                    firstRecentTaskIndex = i;
                }
                recentTaskIndex = i - firstRecentTaskIndex;
            }
            float positionInHotseat = getPositionInHotseat(taskbarDp.numShownHotseatIcons, child,
                    mIsRtl, isAllAppsButton, isTaskbarDividerView,
                    mTaskbarView.isDividerForRecents(), recentTaskIndex);
            if (positionInHotseat == ERROR_POSITION_IN_HOTSEAT_NOT_FOUND) continue;

            float hotseatAdjustedBorderSpace =
                    launcherDp.getHotseatAdjustedBorderSpaceForBubbleBar(child.getContext());
@@ -866,6 +869,58 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
        return controller;
    }

    /**
     * Returns the index of the given child relative to its position in hotseat.
     * Examples:
     * -1 is the item before the first hotseat item.
     * -0.5 is between those (e.g. for the divider).
     * {@link #ERROR_POSITION_IN_HOTSEAT_NOT_FOUND} if there's no calculation relative to hotseat.
     */
    @VisibleForTesting
    float getPositionInHotseat(int numShownHotseatIcons, View child, boolean isRtl,
            boolean isAllAppsButton, boolean isTaskbarDividerView, boolean isDividerForRecents,
            int recentTaskIndex) {
        float positionInHotseat;
        // Note that there is no All Apps button in the hotseat,
        // this position is only used as it's convenient for animation purposes.
        float allAppsButtonPositionInHotseat = isRtl
                // Right after all hotseat items.
                // [HHHHHH]|[>A<]
                ? numShownHotseatIcons
                // Right before all hotseat items.
                // [>A<]|[HHHHHH]
                : -1;
        // Note that there are no recent tasks in the hotseat,
        // this position is only used as it's convenient for animation purposes.
        float firstRecentTaskPositionInHotseat = isRtl
                // After all hotseat icons and All Apps button.
                // [HHHHHH][A]|[>R<R]
                ? numShownHotseatIcons + 1
                // Right after all hotseat items.
                // [A][HHHHHH]|[>R<R]
                : numShownHotseatIcons;
        if (isAllAppsButton) {
            positionInHotseat = allAppsButtonPositionInHotseat;
        }  else if (isTaskbarDividerView) {
            // Note that there is no taskbar divider view in the hotseat,
            // this position is only used as it's convenient for animation purposes.
            float relativePosition = isDividerForRecents
                    ? firstRecentTaskPositionInHotseat
                    : allAppsButtonPositionInHotseat;
            positionInHotseat = relativePosition > 0
                    ? relativePosition - DIVIDER_VIEW_POSITION_OFFSET
                    : relativePosition + DIVIDER_VIEW_POSITION_OFFSET;
        } else if (child.getTag() instanceof ItemInfo) {
            positionInHotseat = ((ItemInfo) child.getTag()).screenId;
        } else if (recentTaskIndex >= 0) {
            positionInHotseat = firstRecentTaskPositionInHotseat + recentTaskIndex;
        } else {
            Log.w(TAG, "Unsupported view found in createIconAlignmentController, v=" + child);
            return ERROR_POSITION_IN_HOTSEAT_NOT_FOUND;
        }
        return positionInHotseat;
    }

    private boolean bubbleBarHasBubbles() {
        return mControllers.bubbleControllers.isPresent()
                && mControllers.bubbleControllers.get().bubbleBarViewController.hasBubbles();
+233 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 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 androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import com.android.launcher3.taskbar.TaskbarViewController.DIVIDER_VIEW_POSITION_OFFSET
import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule
import com.android.launcher3.taskbar.rules.TaskbarUnitTestRule.InjectController
import com.android.launcher3.taskbar.rules.TaskbarWindowSandboxContext
import com.android.launcher3.util.LauncherMultivalentJUnit
import com.android.launcher3.util.LauncherMultivalentJUnit.EmulatedDevices
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(LauncherMultivalentJUnit::class)
@EmulatedDevices(["pixelFoldable2023", "pixelTablet2023"])
/**
 * Legend for the comments below:
 * A: All Apps Button
 * H: Hotseat item
 * |: Divider
 * R: Recent item
 *
 * The comments are formatted in two lines:
 * // Items in taskbar, e.g.               A  |  HHHHHH
 * // Index of items relative to Hotseat: -1 -.5 012345
 */
class TaskbarViewControllerTest {

    private val context = TaskbarWindowSandboxContext.create(getInstrumentation().targetContext)
    @get:Rule val taskbarUnitTestRule = TaskbarUnitTestRule(this, context)

    @InjectController lateinit var taskbarViewController: TaskbarViewController

    @Test
    fun testGetPositionInHotseat_allAppsButton_nonRtl() {
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ 6,
                /* child = */ View(context),
                /* isRtl = */ false,
                /* isAllAppsButton = */ true,
                /* isTaskbarDividerView = */ false,
                /* isDividerForRecents = */ false,
                /* recentTaskIndex = */ -1
            )
        // [>A<] | [HHHHHH]
        //  -1 -.5  012345
        assertThat(position).isEqualTo(-1)
    }

    @Test
    fun testGetPositionInHotseat_allAppsButton_rtl() {
        val numShownHotseatIcons = 6
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ numShownHotseatIcons,
                /* child = */ View(context),
                /* isRtl = */ true,
                /* isAllAppsButton = */ true,
                /* isTaskbarDividerView = */ false,
                /* isDividerForRecents = */ false,
                /* recentTaskIndex = */ -1
            )
        // [HHHHHH] | [>A<]
        //  012345 5.5  6
        assertThat(position).isEqualTo(numShownHotseatIcons)
    }

    @Test
    fun testGetPositionInHotseat_dividerView_notForRecents_nonRtl() {
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ 6,
                /* child = */ View(context),
                /* isRtl = */ false,
                /* isAllAppsButton = */ false,
                /* isTaskbarDividerView = */ true,
                /* isDividerForRecents = */ false,
                /* recentTaskIndex = */ -1
            )
        // [A] >|< [HHHHHH]
        // -1  -.5  012345
        assertThat(position).isEqualTo(-DIVIDER_VIEW_POSITION_OFFSET)
    }

    @Test
    fun testGetPositionInHotseat_dividerView_forRecents_nonRtl() {
        val numShownHotseatIcons = 6
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ numShownHotseatIcons,
                /* child = */ View(context),
                /* isRtl = */ false,
                /* isAllAppsButton = */ false,
                /* isTaskbarDividerView = */ true,
                /* isDividerForRecents = */ true,
                /* recentTaskIndex = */ -1
            )
        // [A] [HHHHHH] >|< [RR]
        // -1   012345  5.5  67
        assertThat(position).isEqualTo(numShownHotseatIcons - DIVIDER_VIEW_POSITION_OFFSET)
    }

    @Test
    fun testGetPositionInHotseat_dividerView_notForRecents_rtl() {
        val numShownHotseatIcons = 6
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ numShownHotseatIcons,
                /* child = */ View(context),
                /* isRtl = */ true,
                /* isAllAppsButton = */ false,
                /* isTaskbarDividerView = */ true,
                /* isDividerForRecents = */ false,
                /* recentTaskIndex = */ -1
            )
        // [HHHHHH] >|< [A]
        //  012345  5.5  6
        assertThat(position).isEqualTo(numShownHotseatIcons - DIVIDER_VIEW_POSITION_OFFSET)
    }

    @Test
    fun testGetPositionInHotseat_dividerView_forRecents_rtl() {
        val numShownHotseatIcons = 6
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ numShownHotseatIcons,
                /* child = */ View(context),
                /* isRtl = */ true,
                /* isAllAppsButton = */ false,
                /* isTaskbarDividerView = */ true,
                /* isDividerForRecents = */ true,
                /* recentTaskIndex = */ -1
            )
        // [HHHHHH][A] >|< [RR]
        //  012345  6  6.5  78
        assertThat(position).isEqualTo(numShownHotseatIcons + DIVIDER_VIEW_POSITION_OFFSET)
    }

    @Test
    fun testGetPositionInHotseat_recentTasks_firstRecentIndex_nonRtl() {
        val numShownHotseatIcons = 6
        val recentTaskIndex = 0
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ numShownHotseatIcons,
                /* child = */ View(context),
                /* isRtl = */ false,
                /* isAllAppsButton = */ false,
                /* isTaskbarDividerView = */ false,
                /* isDividerForRecents = */ false,
                /* recentTaskIndex = */ recentTaskIndex
            )
        // [A][HHHHHH] | [>R<R]
        // -1  012345 5.5  6 7
        assertThat(position).isEqualTo(numShownHotseatIcons + recentTaskIndex)
    }

    @Test
    fun testGetPositionInHotseat_recentTasks_secondRecentIndex_nonRtl() {
        val numShownHotseatIcons = 6
        val recentTaskIndex = 1
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ numShownHotseatIcons,
                /* child = */ View(context),
                /* isRtl = */ false,
                /* isAllAppsButton = */ false,
                /* isTaskbarDividerView = */ false,
                /* isDividerForRecents = */ false,
                /* recentTaskIndex = */ recentTaskIndex
            )
        // [A][HHHHHH] | [R>R<]
        // -1  012345 5.5 6 7
        assertThat(position).isEqualTo(numShownHotseatIcons + recentTaskIndex)
    }

    @Test
    fun testGetPositionInHotseat_recentTasks_firstRecentIndex_rtl() {
        val numShownHotseatIcons = 6
        val recentTaskIndex = 0
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ numShownHotseatIcons,
                /* child = */ View(context),
                /* isRtl = */ true,
                /* isAllAppsButton = */ false,
                /* isTaskbarDividerView = */ false,
                /* isDividerForRecents = */ false,
                /* recentTaskIndex = */ recentTaskIndex
            )
        // [HHHHHH][A] | [>R<R]
        //  012345  6 6.5  7 8
        assertThat(position).isEqualTo(numShownHotseatIcons + 1 + recentTaskIndex)
    }

    @Test
    fun testGetPositionInHotseat_recentTasks_secondRecentIndex_rtl() {
        val numShownHotseatIcons = 6
        val recentTaskIndex = 1
        val position =
            taskbarViewController.getPositionInHotseat(
                /* numShownHotseatIcons = */ numShownHotseatIcons,
                /* child = */ View(context),
                /* isRtl = */ true,
                /* isAllAppsButton = */ false,
                /* isTaskbarDividerView = */ false,
                /* isDividerForRecents = */ false,
                /* recentTaskIndex = */ recentTaskIndex
            )
        // [HHHHHH][A] | [R>R<]
        //  012345  6 6.5 7 8
        assertThat(position).isEqualTo(numShownHotseatIcons + 1 + recentTaskIndex)
    }
}