Add TaskbarView as a child of Hotseat

Instead of keeping the Taskbar window showing above the home screen,
we now integrate a copy of TaskbarView directly into Launcher's view
hierarchy. Most TaskbarController calls apply to both TaskbarViews
(mTaskbarViewInApp and mTaskbarViewOnHome), except for calls related
to Hotseat, which only apply to mTasbkarViewInApp given the real
Hotseat will be showing with mTaskbarViewOnHome.

More cleanup will follow this change.

Test: All taskbar interactions (e.g. drag and drop) continue to work
Bug: 182512211
Bug: 171917176
Change-Id: I0f0b124f652daa85f866e1df8f9e2981540331a0
This commit is contained in:
Tony Wickham
2021-03-22 14:43:58 -07:00
parent 4076cae87f
commit 9ce3b25ef6
13 changed files with 264 additions and 132 deletions

View File

@@ -19,8 +19,6 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static com.android.launcher3.AbstractFloatingView.TYPE_HIDE_TASKBAR;
import static com.android.launcher3.AbstractFloatingView.TYPE_REPLACE_TASKBAR_WITH_HOTSEAT;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
@@ -43,7 +41,6 @@ import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Hotseat;
import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
@@ -54,6 +51,7 @@ import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.AnimatedFloat;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -70,7 +68,8 @@ public class TaskbarController {
private static final String WINDOW_TITLE = "Taskbar";
private final TaskbarContainerView mTaskbarContainerView;
private final TaskbarView mTaskbarView;
private final TaskbarView mTaskbarViewInApp;
private final TaskbarView mTaskbarViewOnHome;
private final BaseQuickstepLauncher mLauncher;
private final WindowManager mWindowManager;
// Layout width and height of the Taskbar in the default state.
@@ -91,14 +90,17 @@ public class TaskbarController {
private @Nullable Animator mAnimator;
private boolean mIsAnimatingToLauncher;
private boolean mIsAnimatingToApp;
public TaskbarController(BaseQuickstepLauncher launcher,
TaskbarContainerView taskbarContainerView) {
TaskbarContainerView taskbarContainerView, TaskbarView taskbarViewOnHome) {
mLauncher = launcher;
mTaskbarContainerView = taskbarContainerView;
mTaskbarContainerView.construct(createTaskbarContainerViewCallbacks());
mTaskbarView = mTaskbarContainerView.findViewById(R.id.taskbar_view);
mTaskbarView.construct(createTaskbarViewCallbacks());
mTaskbarViewInApp = mTaskbarContainerView.findViewById(R.id.taskbar_view);
mTaskbarViewInApp.construct(createTaskbarViewCallbacks());
mTaskbarViewOnHome = taskbarViewOnHome;
mTaskbarViewOnHome.construct(createTaskbarViewCallbacks());
mWindowManager = mLauncher.getWindowManager();
mTaskbarSize = new Point(MATCH_PARENT, mLauncher.getDeviceProfile().taskbarSize);
mTaskbarStateHandler = mLauncher.getTaskbarStateHandler();
@@ -115,12 +117,13 @@ public class TaskbarController {
return new TaskbarVisibilityControllerCallbacks() {
@Override
public void updateTaskbarBackgroundAlpha(float alpha) {
mTaskbarView.setBackgroundAlpha(alpha);
mTaskbarViewInApp.setBackgroundAlpha(alpha);
}
@Override
public void updateTaskbarVisibilityAlpha(float alpha) {
mTaskbarContainerView.setAlpha(alpha);
mTaskbarViewOnHome.setAlpha(alpha);
}
};
}
@@ -196,7 +199,7 @@ public class TaskbarController {
public View.OnLongClickListener getItemOnLongClickListener() {
return view -> {
if (mLauncher.hasBeenResumed() && view.getTag() instanceof ItemInfo) {
alignRealHotseatWithTaskbar();
// TODO: remove this path
return mDragController.startWorkspaceDragOnLongClick(view);
} else {
return mDragController.startSystemDragOnLongClick(view);
@@ -205,11 +208,24 @@ public class TaskbarController {
}
@Override
public int getEmptyHotseatViewVisibility() {
public int getEmptyHotseatViewVisibility(TaskbarView taskbarView) {
// When on the home screen, we want the empty hotseat views to take up their full
// space so that the others line up with the home screen hotseat.
return mLauncher.hasBeenResumed() || mIsAnimatingToLauncher
? View.INVISIBLE : View.GONE;
boolean isOnHomeScreen = taskbarView == mTaskbarViewOnHome
|| mLauncher.hasBeenResumed() || mIsAnimatingToLauncher;
return isOnHomeScreen ? View.INVISIBLE : View.GONE;
}
@Override
public float getNonIconScale(TaskbarView taskbarView) {
return taskbarView == mTaskbarViewOnHome ? getTaskbarScaleOnHome() : 1f;
}
@Override
public void onItemPositionsChanged(TaskbarView taskbarView) {
if (taskbarView == mTaskbarViewOnHome) {
alignRealHotseatWithTaskbar();
}
}
};
}
@@ -218,7 +234,7 @@ public class TaskbarController {
return new TaskbarHotseatControllerCallbacks() {
@Override
public void updateHotseatItems(ItemInfo[] hotseatItemInfos) {
mTaskbarView.updateHotseatItems(hotseatItemInfos);
mTaskbarViewInApp.updateHotseatItems(hotseatItemInfos);
mLatestLoadedHotseatItems = hotseatItemInfos;
dedupeAndUpdateRecentItems();
}
@@ -235,7 +251,8 @@ public class TaskbarController {
@Override
public void updateRecentTaskAtIndex(int taskIndex, Task task) {
mTaskbarView.updateRecentTaskAtIndex(taskIndex, task);
mTaskbarViewInApp.updateRecentTaskAtIndex(taskIndex, task);
mTaskbarViewOnHome.updateRecentTaskAtIndex(taskIndex, task);
}
};
}
@@ -244,16 +261,20 @@ public class TaskbarController {
* Initializes the Taskbar, including adding it to the screen.
*/
public void init() {
mTaskbarView.init(mHotseatController.getNumHotseatIcons(),
mTaskbarViewInApp.init(mHotseatController.getNumHotseatIcons(),
mRecentsController.getNumRecentIcons());
mTaskbarContainerView.init(mTaskbarView);
mTaskbarViewOnHome.init(mHotseatController.getNumHotseatIcons(),
mRecentsController.getNumRecentIcons());
mTaskbarContainerView.init(mTaskbarViewInApp);
addToWindowManager();
mTaskbarStateHandler.setTaskbarCallbacks(createTaskbarStateHandlerCallbacks());
mTaskbarVisibilityController.init();
mHotseatController.init();
mRecentsController.init();
SCALE_PROPERTY.set(mTaskbarView, mLauncher.hasBeenResumed() ? getTaskbarScaleOnHome() : 1f);
SCALE_PROPERTY.set(mTaskbarViewInApp, mLauncher.hasBeenResumed()
? getTaskbarScaleOnHome() : 1f);
updateWhichTaskbarViewIsVisible();
}
private TaskbarStateHandlerCallbacks createTaskbarStateHandlerCallbacks() {
@@ -274,7 +295,8 @@ public class TaskbarController {
mAnimator.end();
}
mTaskbarView.cleanup();
mTaskbarViewInApp.cleanup();
mTaskbarViewOnHome.cleanup();
mTaskbarContainerView.cleanup();
removeFromWindowManager();
mTaskbarStateHandler.setTaskbarCallbacks(null);
@@ -313,7 +335,7 @@ public class TaskbarController {
TaskbarContainerView.LayoutParams taskbarLayoutParams =
new TaskbarContainerView.LayoutParams(mTaskbarSize.x, mTaskbarSize.y);
taskbarLayoutParams.gravity = gravity;
mTaskbarView.setLayoutParams(taskbarLayoutParams);
mTaskbarViewInApp.setLayoutParams(taskbarLayoutParams);
mWindowManager.addView(mTaskbarContainerView, mWindowLayoutParams);
}
@@ -330,7 +352,6 @@ public class TaskbarController {
mAnimator = createAnimToLauncher(null, duration);
} else {
mAnimator = createAnimToApp(duration);
replaceTaskbarWithHotseatOrViceVersa();
}
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
@@ -351,36 +372,41 @@ public class TaskbarController {
if (toState != null) {
mTaskbarStateHandler.setStateWithAnimation(toState, new StateAnimationConfig(), anim);
}
anim.addFloat(mTaskbarView, SCALE_PROPERTY, mTaskbarView.getScaleX(),
anim.addFloat(mTaskbarViewInApp, SCALE_PROPERTY, mTaskbarViewInApp.getScaleX(),
getTaskbarScaleOnHome(), LINEAR);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mIsAnimatingToLauncher = true;
mTaskbarView.updateHotseatItemsVisibility();
mTaskbarViewInApp.updateHotseatItemsVisibility();
}
@Override
public void onAnimationEnd(Animator animation) {
mIsAnimatingToLauncher = false;
updateWhichTaskbarViewIsVisible();
}
});
anim.addOnFrameCallback(this::alignRealHotseatWithTaskbar);
return anim.buildAnim();
}
private Animator createAnimToApp(long duration) {
PendingAnimation anim = new PendingAnimation(duration);
anim.add(mTaskbarVisibilityController.createAnimToBackgroundAlpha(1, duration));
anim.addFloat(mTaskbarView, SCALE_PROPERTY, mTaskbarView.getScaleX(), 1f, LINEAR);
anim.addFloat(mTaskbarViewInApp, SCALE_PROPERTY, mTaskbarViewInApp.getScaleX(), 1f, LINEAR);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mTaskbarView.updateHotseatItemsVisibility();
setReplaceTaskbarWithHotseat(false);
mIsAnimatingToApp = true;
mTaskbarViewInApp.updateHotseatItemsVisibility();
updateWhichTaskbarViewIsVisible();
}
@Override
public void onAnimationEnd(Animator animation) {
mIsAnimatingToApp = false;
}
});
return anim.buildAnim();
@@ -405,11 +431,11 @@ public class TaskbarController {
* @return Whether any Taskbar item could handle the given MotionEvent if given the chance.
*/
public boolean isEventOverAnyTaskbarItem(MotionEvent ev) {
return mTaskbarView.isEventOverAnyItem(ev);
return mTaskbarViewInApp.isEventOverAnyItem(ev);
}
public boolean isDraggingItem() {
return mTaskbarView.isDraggingItem();
return mTaskbarViewInApp.isDraggingItem() || mTaskbarViewOnHome.isDraggingItem();
}
private void dedupeAndUpdateRecentItems() {
@@ -454,7 +480,8 @@ public class TaskbarController {
tasksArray[tasksArray.length - 1 - i] = task;
}
mTaskbarView.updateRecentTasks(tasksArray);
mTaskbarViewInApp.updateRecentTasks(tasksArray);
mTaskbarViewOnHome.updateRecentTasks(tasksArray);
mRecentsController.loadIconsForTasks(tasksArray);
}
@@ -475,10 +502,11 @@ public class TaskbarController {
int hotseatHeight = grid.workspacePadding.bottom + grid.taskbarSize;
int hotseatTopDiff = hotseatHeight - grid.taskbarSize;
mTaskbarView.getHotseatBoundsAtScale(getTaskbarScaleOnHome()).roundOut(hotseatBounds);
mLauncher.getHotseat().setPadding(hotseatBounds.left, hotseatBounds.top + hotseatTopDiff,
mTaskbarView.getWidth() - hotseatBounds.right,
mTaskbarView.getHeight() - hotseatBounds.bottom);
mTaskbarViewOnHome.getHotseatBounds().roundOut(hotseatBounds);
mLauncher.getHotseat().setPadding(hotseatBounds.left,
hotseatBounds.top + hotseatTopDiff,
mTaskbarViewOnHome.getWidth() - hotseatBounds.right,
mTaskbarViewOnHome.getHeight() - hotseatBounds.bottom);
}
/**
@@ -486,36 +514,32 @@ public class TaskbarController {
* show the real one instead.
*/
public void onLauncherDragLayerHierarchyChanged() {
replaceTaskbarWithHotseatOrViceVersa();
// TODO: remove, as this is a no-op now
}
private void replaceTaskbarWithHotseatOrViceVersa() {
boolean replaceTaskbarWithHotseat = AbstractFloatingView.getTopOpenViewWithType(mLauncher,
TYPE_REPLACE_TASKBAR_WITH_HOTSEAT) != null;
if (!mLauncher.hasBeenResumed()) {
replaceTaskbarWithHotseat = false;
}
setReplaceTaskbarWithHotseat(replaceTaskbarWithHotseat);
boolean hideTaskbar = AbstractFloatingView.getTopOpenViewWithType(mLauncher,
TYPE_HIDE_TASKBAR) != null;
mTaskbarVisibilityController.animateToVisibilityForFloatingView(hideTaskbar ? 0f : 1f);
}
private void setReplaceTaskbarWithHotseat(boolean replaceTaskbarWithHotseat) {
Hotseat hotseat = mLauncher.getHotseat();
if (replaceTaskbarWithHotseat) {
alignRealHotseatWithTaskbar();
hotseat.getReplaceTaskbarAlpha().setValue(1f);
mTaskbarView.setHotseatViewsHidden(true);
private void updateWhichTaskbarViewIsVisible() {
boolean isInApp = !mLauncher.hasBeenResumed() || mIsAnimatingToLauncher
|| mIsAnimatingToApp;
if (isInApp) {
mTaskbarViewInApp.setVisibility(View.VISIBLE);
mTaskbarViewOnHome.setVisibility(View.INVISIBLE);
mLauncher.getHotseat().setIconsAlpha(0);
} else {
hotseat.getReplaceTaskbarAlpha().setValue(0f);
mTaskbarView.setHotseatViewsHidden(false);
mTaskbarViewInApp.setVisibility(View.INVISIBLE);
mTaskbarViewOnHome.setVisibility(View.VISIBLE);
mLauncher.getHotseat().setIconsAlpha(1);
}
}
private float getTaskbarScaleOnHome() {
return 1f / mTaskbarContainerView.getTaskbarActivityContext().getTaskbarIconScale();
/**
* Returns the ratio of the taskbar icon size on home vs in an app.
*/
public float getTaskbarScaleOnHome() {
DeviceProfile inAppDp = mTaskbarContainerView.getTaskbarActivityContext()
.getDeviceProfile();
DeviceProfile onHomeDp = ActivityContext.lookupContext(mTaskbarViewOnHome.getContext())
.getDeviceProfile();
return (float) onHomeDp.cellWidthPx / inAppDp.cellWidthPx;
}
/**
@@ -561,7 +585,10 @@ public class TaskbarController {
protected interface TaskbarViewCallbacks {
View.OnClickListener getItemOnClickListener();
View.OnLongClickListener getItemOnLongClickListener();
int getEmptyHotseatViewVisibility();
int getEmptyHotseatViewVisibility(TaskbarView taskbarView);
/** Returns how much to scale non-icon elements such as spacing and dividers. */
float getNonIconScale(TaskbarView taskbarView);
void onItemPositionsChanged(TaskbarView taskbarView);
}
/**