Merge "Keep live tile running when TaskMenuView is showing" into tm-dev
diff --git a/build.gradle b/build.gradle
index e4ade88..68ed73d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -170,7 +170,7 @@
protobuf {
// Configure the protoc executable
protoc {
- artifact = "com.google.protobuf:protoc:${protocVersion}"
+ artifact = "com.google.protobuf:protoc:${protocVersion}${PROTO_ARCH_SUFFIX}"
}
generateProtoTasks {
all().each { task ->
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index 05e269b..e381cb0 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -15,6 +15,11 @@
*/
-->
<resources>
- <dimen name="overview_grid_row_spacing">44dp</dimen>
+ <dimen name="overview_task_margin">16dp</dimen>
+ <dimen name="overview_task_margin_grid">16dp</dimen>
+ <dimen name="overview_grid_side_margin">64dp</dimen>
+ <dimen name="overview_grid_row_spacing">36dp</dimen>
<dimen name="overview_page_spacing">44dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
+ <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
</resources>
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
index 5efcc4d..8e57ea6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduPagedView.java
@@ -52,7 +52,7 @@
}
@Override
- protected int getChildGap() {
+ protected int getChildGap(int fromIndex, int toIndex) {
return mTaskbarEduView.getPaddingLeft() + mTaskbarEduView.getPaddingRight();
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index 5ce4fa7..494d21e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -89,8 +89,13 @@
*/
private final TaskbarSharedState mSharedState = new TaskbarSharedState();
- private static final int CHANGE_FLAGS = CHANGE_ACTIVE_SCREEN | CHANGE_DENSITY
- | CHANGE_SUPPORTED_BOUNDS | CHANGE_NAVIGATION_MODE;
+ /**
+ * We use WindowManager's ComponentCallbacks() for most of the config changes, however for
+ * navigation mode, that callback gets called too soon, before it's internal navigation mode
+ * reflects the current one.
+ * DisplayController's callback is delayed enough to get the correct nav mode value
+ */
+ private static final int CHANGE_FLAGS = CHANGE_NAVIGATION_MODE;
private boolean mUserUnlocked = false;
@@ -108,19 +113,29 @@
@Override
public void onConfigurationChanged(Configuration newConfig) {
+ DeviceProfile dp = mUserUnlocked
+ ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext)
+ : null;
int configDiff = mOldConfig.diff(newConfig);
int configsRequiringRecreate = ActivityInfo.CONFIG_ASSETS_PATHS
- | ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE;
+ | ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_UI_MODE
+ | ActivityInfo.CONFIG_DENSITY | ActivityInfo.CONFIG_SCREEN_SIZE;
if ((configDiff & configsRequiringRecreate) != 0) {
- // Color has changed, recreate taskbar to reload background color & icons.
- recreateTaskbar();
+ if ((configDiff & ActivityInfo.CONFIG_SCREEN_SIZE) != 0 &&
+ mTaskbarActivityContext != null && dp != null) {
+ DeviceProfile oldDp = mTaskbarActivityContext.getDeviceProfile();
+ // Additional check since this callback gets fired multiple times w/o
+ // screen size changing
+ if (dp.widthPx != oldDp.widthPx || dp.heightPx != oldDp.heightPx) {
+ recreateTaskbar();
+ }
+ } else {
+ // Color has changed, recreate taskbar to reload background color & icons.
+ recreateTaskbar();
+ }
} else {
// Config change might be handled without re-creating the taskbar
if (mTaskbarActivityContext != null) {
- DeviceProfile dp = mUserUnlocked
- ? LauncherAppState.getIDP(mContext).getDeviceProfile(mContext)
- : null;
-
if (dp != null && dp.isTaskbarPresent) {
mTaskbarActivityContext.updateDeviceProfile(dp.copy(mContext));
}
diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
index 17baa3a..a7bdcc6 100644
--- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
+++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.java
@@ -54,6 +54,12 @@
public static final int TYPE_TOGGLE = 4;
public static final int TYPE_HOME = 5;
+ /**
+ * Use case for needing a queue is double tapping recents button in 3 button nav.
+ * Size of 2 should be enough. We'll toss in one more because we're kind hearted.
+ */
+ private final static int MAX_QUEUE_SIZE = 3;
+
private static final String TRANSITION_NAME = "Transition:toOverview";
private final TouchInteractionService mService;
@@ -105,10 +111,15 @@
}
/**
- * Adds a command to be executed next, after all pending tasks are completed
+ * Adds a command to be executed next, after all pending tasks are completed.
+ * Max commands that can be queued is {@link #MAX_QUEUE_SIZE}.
+ * Requests after reaching that limit will be silently dropped.
*/
@BinderThread
public void addCommand(int type) {
+ if (mPendingCommands.size() > MAX_QUEUE_SIZE) {
+ return;
+ }
CommandInfo cmd = new CommandInfo(type);
MAIN_EXECUTOR.execute(() -> addCommand(cmd));
}
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 27a748d..79b15c7 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -306,7 +306,7 @@
private void setBanner(@Nullable View view) {
mBanner = view;
- if (view != null) {
+ if (view != null && mTaskView.getRecentsView() != null) {
setupAndAddBanner();
setBannerOutline();
}
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index d9f668d..b9615ab 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -271,7 +271,8 @@
getPagedOrientationHandler().setSplitIconParams(mIconView, mIconView2,
taskIconHeight, mSnapshotView.getMeasuredWidth(), mSnapshotView.getMeasuredHeight(),
- isRtl, deviceProfile, mSplitBoundsConfig);
+ getMeasuredHeight(), getMeasuredWidth(), isRtl, deviceProfile,
+ mSplitBoundsConfig);
}
private void updateSecondaryDwbPlacement() {
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index a6b8897..3c10e21 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1078,10 +1078,15 @@
private int getSnapToLastTaskScrollDiff() {
// Snap to a position where ClearAll is just invisible.
int screenStart = mOrientationHandler.getPrimaryScroll(this);
- int clearAllWidth = mOrientationHandler.getPrimarySize(mClearAllButton);
int clearAllScroll = getScrollForPage(indexOfChild(mClearAllButton));
- int targetScroll = clearAllScroll + (mIsRtl ? clearAllWidth : -clearAllWidth);
- return screenStart - targetScroll;
+ int clearAllWidth = mOrientationHandler.getPrimarySize(mClearAllButton);
+ int lastTaskScroll = getLastTaskScroll(clearAllScroll, clearAllWidth);
+ return screenStart - lastTaskScroll;
+ }
+
+ private int getLastTaskScroll(int clearAllScroll, int clearAllWidth) {
+ int distance = clearAllWidth + getClearAllExtraPageSpacing();
+ return clearAllScroll + (mIsRtl ? distance : -distance);
}
private int getSnapToFocusedTaskScrollDiff(boolean isClearAllHidden) {
@@ -4515,6 +4520,19 @@
}
@Override
+ protected int getChildGap(int fromIndex, int toIndex) {
+ int clearAllIndex = indexOfChild(mClearAllButton);
+ return fromIndex == clearAllIndex || toIndex == clearAllIndex
+ ? getClearAllExtraPageSpacing() : 0;
+ }
+
+ private int getClearAllExtraPageSpacing() {
+ return showAsGrid()
+ ? Math.max(mActivity.getDeviceProfile().overviewGridSideMargin - mPageSpacing, 0)
+ : 0;
+ }
+
+ @Override
protected void updateMinAndMaxScrollX() {
super.updateMinAndMaxScrollX();
if (DEBUG) {
@@ -4596,9 +4614,10 @@
TaskView taskView = requireTaskViewAt(i);
float scrollDiff = taskView.getScrollAdjustment(showAsFullscreen, showAsGrid);
int pageScroll = newPageScrolls[i] + (int) scrollDiff;
- if ((mIsRtl && pageScroll < clearAllScroll + clearAllWidth)
- || (!mIsRtl && pageScroll > clearAllScroll - clearAllWidth)) {
- pageScroll = clearAllScroll + (mIsRtl ? clearAllWidth : -clearAllWidth);
+ int lastTaskScroll = getLastTaskScroll(clearAllScroll, clearAllWidth);
+ if ((mIsRtl && pageScroll < lastTaskScroll)
+ || (!mIsRtl && pageScroll > lastTaskScroll)) {
+ pageScroll = lastTaskScroll;
}
if (outPageScrolls[i] != pageScroll) {
pageScrollChanged = true;
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index c4bed26..ce033e5 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -1000,8 +1000,11 @@
// resetViewTransforms is called during Quickswitch scrolling.
mDismissTranslationX = mTaskOffsetTranslationX =
mTaskResistanceTranslationX = mSplitSelectTranslationX = mGridEndTranslationX = 0f;
- mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY =
- mSplitSelectTranslationY = 0f;
+ mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = 0f;
+ if (getRecentsView() == null || !getRecentsView().isSplitSelectionActive()) {
+ mSplitSelectTranslationY = 0f;
+ }
+
setSnapshotScale(1f);
applyTranslationX();
applyTranslationY();
diff --git a/res/drawable/drop_target_frame.xml b/res/drawable/drop_target_frame.xml
index 666a96e..9f04103 100644
--- a/res/drawable/drop_target_frame.xml
+++ b/res/drawable/drop_target_frame.xml
@@ -17,6 +17,6 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/transparent" />
- <corners android:radius="28dp" />
+ <corners android:radius="80dp" />
<stroke android:width="2dp" android:color="?attr/workspaceAccentColor" />
</shape>
\ No newline at end of file
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 662b86e..422240c 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -22,8 +22,22 @@
<dimen name="fastscroll_popup_text_size">24dp</dimen>
<!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">15.28dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
+ <dimen name="dynamic_grid_drop_target_size">36dp</dimen>
+ <dimen name="cell_layout_padding">20dp</dimen>
<!-- Hotseat -->
<dimen name="dynamic_grid_hotseat_side_padding">16dp</dimen>
+ <dimen name="spring_loaded_hotseat_top_margin">45dp</dimen>
+
+ <!-- Dragging -->
+ <dimen name="drop_target_button_gap">28dp</dimen>
+ <dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
+ <dimen name="drop_target_button_drawable_vertical_padding">2dp</dimen>
+ <dimen name="drop_target_top_margin">6dp</dimen>
+ <dimen name="drop_target_bottom_margin">6dp</dimen>
+
+ <!-- Workspace grid visualization parameters -->
+ <dimen name="grid_visualization_horizontal_cell_spacing">24dp</dimen>
</resources>
diff --git a/res/values-sw600dp-land/dimens.xml b/res/values-sw600dp-land/dimens.xml
new file mode 100644
index 0000000..6c5be91
--- /dev/null
+++ b/res/values-sw600dp-land/dimens.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2022 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.
+ -->
+
+<resources>
+ <!-- Hotseat -->
+ <dimen name="spring_loaded_hotseat_top_margin">44dp</dimen>
+
+ <!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">11.33dp</dimen>
+ <dimen name="cell_layout_padding">11.33dp</dimen>
+
+ <!-- Dragging -->
+ <dimen name="drop_target_top_margin">0dp</dimen>
+ <dimen name="drop_target_bottom_margin">16dp</dimen>
+</resources>
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 92f806e..501ead6 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -32,8 +32,22 @@
<dimen name="fastscroll_popup_text_size">32dp</dimen>
<!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">9dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">7dp</dimen>
+ <dimen name="cell_layout_padding">9dp</dimen>
+
<!-- Hotseat -->
<dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
+ <dimen name="spring_loaded_hotseat_top_margin">97dp</dimen>
+
+<!-- Dragging -->
+ <dimen name="drop_target_top_margin">34dp</dimen>
+ <dimen name="drop_target_bottom_margin">16dp</dimen>
+ <dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
+ <dimen name="drop_target_button_drawable_vertical_padding">16dp</dimen>
+ <dimen name="dynamic_grid_drop_target_size">56dp</dimen>
+
+<!-- Workspace grid visualization parameters -->
+ <dimen name="grid_visualization_horizontal_cell_spacing">6dp</dimen>
</resources>
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
index 9821526..33da4a1 100644
--- a/res/values-sw720dp-land/dimens.xml
+++ b/res/values-sw720dp-land/dimens.xml
@@ -15,9 +15,16 @@
-->
<resources>
- <!-- Widget picker-->
+<!-- Dragging-->
+ <dimen name="drop_target_top_margin">0dp</dimen>
+ <dimen name="drop_target_bottom_margin">32dp</dimen>
+<!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">21.93dp</dimen>
+ <dimen name="cell_layout_padding">29.33dp</dimen>
+<!-- Hotseat -->
+ <dimen name="spring_loaded_hotseat_top_margin">64dp</dimen>
+<!-- Widget picker-->
<dimen name="widget_list_horizontal_margin">49dp</dimen>
-
- <!-- Bottom sheet-->
+<!-- Bottom sheet-->
<dimen name="bottom_sheet_extra_top_padding">0dp</dimen>
</resources>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 7ebc3f8..b4c8837 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -17,6 +17,19 @@
<resources>
<!-- AllApps -->
<dimen name="all_apps_bottom_sheet_horizontal_padding">65dp</dimen>
+<!-- Dynamic grid -->
+ <dimen name="dynamic_grid_edge_margin">27.59dp</dimen>
+ <dimen name="cell_layout_padding">36dp</dimen>
+<!-- Dragging -->
+ <dimen name="drop_target_text_size">20sp</dimen>
+ <dimen name="dynamic_grid_drop_target_size">72dp</dimen>
+ <dimen name="drop_target_button_drawable_horizontal_padding">24dp</dimen>
+ <dimen name="drop_target_button_drawable_vertical_padding">20dp</dimen>
+ <dimen name="drop_target_button_gap">32dp</dimen>
+ <dimen name="drop_target_top_margin">32dp</dimen>
+ <dimen name="drop_target_bottom_margin">32dp</dimen>
+<!-- Hotseat -->
+ <dimen name="spring_loaded_hotseat_top_margin">164dp</dimen>
<!-- Widget picker-->
<dimen name="widget_list_horizontal_margin">30dp</dimen>
diff --git a/res/values/config.xml b/res/values/config.xml
index e2fd0e3..5e90bea 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -22,9 +22,6 @@
<item type="id" name="drag_event_parity" />
<!-- AllApps & Launcher transitions -->
- <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
- <integer name="config_workspaceSpringLoadShrinkPercentage">85</integer>
-
<!-- The duration of the animation from search hint to text entry -->
<integer name="config_searchHintAnimationDuration">50</integer>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 338e218..a6abee2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -19,14 +19,14 @@
<dimen name="click_shadow_elevation">4dp</dimen>
<!-- Dynamic Grid -->
- <dimen name="dynamic_grid_edge_margin">8dp</dimen>
+ <dimen name="dynamic_grid_edge_margin">10.77dp</dimen>
<dimen name="dynamic_grid_left_right_margin">8dp</dimen>
<dimen name="dynamic_grid_icon_drawable_padding">7dp</dimen>
<!-- Minimum space between workspace and hotseat in spring loaded mode -->
<dimen name="dynamic_grid_min_spring_loaded_space">8dp</dimen>
<dimen name="dynamic_grid_cell_border_spacing">16dp</dimen>
- <dimen name="dynamic_grid_cell_layout_padding">5.5dp</dimen>
+ <dimen name="cell_layout_padding">10.77dp</dimen>
<dimen name="dynamic_grid_cell_padding_x">8dp</dimen>
<!-- Hotseat -->
@@ -34,6 +34,7 @@
<dimen name="dynamic_grid_hotseat_bottom_padding">2dp</dimen>
<dimen name="dynamic_grid_hotseat_bottom_tall_padding">0dp</dimen>
<dimen name="inline_qsb_bottom_margin">0dp</dimen>
+ <dimen name="spring_loaded_hotseat_top_margin">76dp</dimen>
<!-- Qsb -->
<!-- Used for adjusting the position of QSB when placed in hotseat. This is a ratio and a higher
@@ -55,8 +56,10 @@
<dimen name="workspace_page_indicator_overlap_workspace">0dp</dimen>
<!-- Drop target bar -->
- <dimen name="dynamic_grid_drop_target_size">52dp</dimen>
+ <dimen name="dynamic_grid_drop_target_size">56dp</dimen>
<dimen name="drop_target_vertical_gap">20dp</dimen>
+ <dimen name="drop_target_top_margin">36dp</dimen>
+ <dimen name="drop_target_bottom_margin">16dp</dimen>
<!-- App Widget resize frame -->
<dimen name="widget_handle_margin">13dp</dimen>
@@ -206,6 +209,9 @@
<dimen name="drop_target_shadow_elevation">2dp</dimen>
<dimen name="drop_target_bar_margin_horizontal">4dp</dimen>
<dimen name="drop_target_button_drawable_padding">8dp</dimen>
+ <dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
+ <dimen name="drop_target_button_drawable_vertical_padding">8dp</dimen>
+ <dimen name="drop_target_button_gap">22dp</dimen>
<!-- the distance an icon must be dragged before button drop targets accept it -->
<dimen name="drag_distanceThreshold">30dp</dimen>
@@ -358,8 +364,9 @@
<!-- Workspace grid visualization parameters -->
- <dimen name="grid_visualization_rounding_radius">22dp</dimen>
- <dimen name="grid_visualization_cell_spacing">6dp</dimen>
+ <dimen name="grid_visualization_rounding_radius">28dp</dimen>
+ <dimen name="grid_visualization_horizontal_cell_spacing">6dp</dimen>
+ <dimen name="grid_visualization_vertical_cell_spacing">6dp</dimen>
<!-- Search results related parameters -->
<dimen name="search_row_icon_size">48dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 868b5f3..267f9c3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -60,9 +60,9 @@
<string name="widget_preview_context_description"><xliff:g id="widget_name" example="Calendar month view">%1$s</xliff:g> widget</string>
<!-- Message to tell the user to press and hold a widget/icon to add it to the home screen.
[CHAR LIMIT=NONE] -->
- <string name="add_item_request_drag_hint">Touch & hold the widget to move it around the Home screen</string>
+ <string name="add_item_request_drag_hint">Touch & hold the widget to move it around the home screen</string>
<!-- Button label to automatically add a widget to home screen [CHAR_LIMIT=50] -->
- <string name="add_to_home_screen">Add to Home screen</string>
+ <string name="add_to_home_screen">Add to home screen</string>
<!-- Accessibility spoken message announced when a widget gets added to the home screen using a
button in a dialog. [CHAR_LIMIT=none] -->
<string name="added_to_home_screen_accessibility_text"><xliff:g id="widget_name" example="Calendar month view">%1$s</xliff:g> widget added to home screen</string>
@@ -108,7 +108,7 @@
<string name="widget_education_header">Useful info at your fingertips</string>
<!-- Dialog text. This dialog lets a user know how they can use widgets on their phone.
[CHAR_LIMIT=NONE] -->
- <string name="widget_education_content">To get info without opening apps, you can add widgets to your Home screen</string>
+ <string name="widget_education_content">To get info without opening apps, you can add widgets to your home screen</string>
<!-- Text on an educational tip on widget informing users that they can change widget settings.
[CHAR_LIMIT=NONE] -->
@@ -147,7 +147,7 @@
<skip />
<!-- Error message when a user can't add more apps, widgets, or shortcuts to a Home screen. -->
- <string name="out_of_space">No room on this Home screen</string>
+ <string name="out_of_space">No room on this home screen</string>
<!-- Error message when user has filled the hotseat -->
<string name="hotseat_out_of_space">No more room in the Favorites tray</string>
@@ -181,15 +181,15 @@
<string name="permdesc_install_shortcut">Allows an app to add
shortcuts without user intervention.</string>
<!-- Permission short label -->
- <string name="permlab_read_settings">read Home settings and shortcuts</string>
+ <string name="permlab_read_settings">read home settings and shortcuts</string>
<!-- Permission description -->
<string name="permdesc_read_settings">Allows the app to read the settings and
- shortcuts in Home.</string>
+ shortcuts in home.</string>
<!-- Permission short label -->
- <string name="permlab_write_settings">write Home settings and shortcuts</string>
+ <string name="permlab_write_settings">write home settings and shortcuts</string>
<!-- Permission description -->
<string name="permdesc_write_settings">Allows the app to change the settings and
- shortcuts in Home.</string>
+ shortcuts in home.</string>
<!-- Toast shown on clicking a direct call shortcut. [CHAR_LIMIT=80] -->
<string name="msg_no_phone_permission"><xliff:g id="app_name" example="Launcher3">%1$s</xliff:g> is not allowed to make phone calls</string>
@@ -259,7 +259,7 @@
<!-- Strings for settings -->
<!-- Title for Allow Rotation setting. [CHAR LIMIT=50] -->
- <string name="allow_rotation_title">Allow Home screen rotation</string>
+ <string name="allow_rotation_title">Allow home screen rotation</string>
<!-- Text explaining when the home screen will get rotated. [CHAR LIMIT=100] -->
<string name="allow_rotation_desc">When phone is rotated</string>
<!-- Title for Notification dots setting. Tapping this will link to the system Notifications settings screen where the user can turn off notification dots globally. [CHAR LIMIT=50] -->
@@ -278,7 +278,7 @@
<string name="notification_dots_service_title">Show notification dots</string>
<!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=60] -->
- <string name="auto_add_shortcuts_label">Add app icons to Home screen</string>
+ <string name="auto_add_shortcuts_label">Add app icons to home screen</string>
<!-- Text description of the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=NONE] -->
<string name="auto_add_shortcuts_description">For new apps</string>
@@ -312,7 +312,7 @@
<!-- Strings for accessibility actions -->
<!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] -->
- <string name="action_add_to_workspace">Add to Home screen</string>
+ <string name="action_add_to_workspace">Add to home screen</string>
<!-- Accessibility action to move item to the current location. [CHAR_LIMIT=30] -->
<string name="action_move_here">Move item here</string>
@@ -357,7 +357,7 @@
<string name="folder_created">Folder created</string>
<!-- Accessibility action to move an item from folder to workspace. [CHAR_LIMIT=30] -->
- <string name="action_move_to_workspace">Move to Home screen</string>
+ <string name="action_move_to_workspace">Move to home screen</string>
<!-- Accessibility action to resize a widget. [CHAR_LIMIT=30] -->
<string name="action_resize">Resize</string>
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index ad4cae4..e184a91 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -148,7 +148,8 @@
private boolean mVisualizeDropLocation = true;
private RectF mVisualizeGridRect = new RectF();
private Paint mVisualizeGridPaint = new Paint();
- private int mGridVisualizationPadding;
+ private int mGridVisualizationPaddingX;
+ private int mGridVisualizationPaddingY;
private int mGridVisualizationRoundingRadius;
private float mGridAlpha = 0f;
private int mGridColor = 0;
@@ -275,8 +276,10 @@
mBackground.setAlpha(0);
mGridColor = Themes.getAttrColor(getContext(), R.attr.workspaceAccentColor);
- mGridVisualizationPadding =
- res.getDimensionPixelSize(R.dimen.grid_visualization_cell_spacing);
+ mGridVisualizationPaddingX = res.getDimensionPixelSize(
+ R.dimen.grid_visualization_horizontal_cell_spacing);
+ mGridVisualizationPaddingY = res.getDimensionPixelSize(
+ R.dimen.grid_visualization_vertical_cell_spacing);
mGridVisualizationRoundingRadius =
res.getDimensionPixelSize(R.dimen.grid_visualization_rounding_radius);
mReorderPreviewAnimationMagnitude = (REORDER_PREVIEW_MAGNITUDE * deviceProfile.iconSizePx);
@@ -573,8 +576,8 @@
protected void visualizeGrid(Canvas canvas) {
DeviceProfile dp = mActivity.getDeviceProfile();
- int paddingX = (int) Math.min((mCellWidth - dp.iconSizePx) / 2, mGridVisualizationPadding);
- int paddingY = (int) Math.min((mCellHeight - dp.iconSizePx) / 2, mGridVisualizationPadding);
+ int paddingX = Math.min((mCellWidth - dp.iconSizePx) / 2, mGridVisualizationPaddingX);
+ int paddingY = Math.min((mCellHeight - dp.iconSizePx) / 2, mGridVisualizationPaddingY);
mVisualizeGridRect.set(paddingX, paddingY,
mCellWidth - paddingX,
mCellHeight - paddingY);
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 09affd7..91fa4ca 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -94,18 +94,16 @@
private static final float TALL_DEVICE_EXTRA_SPACE_THRESHOLD_DP = 252;
private static final float TALL_DEVICE_MORE_EXTRA_SPACE_THRESHOLD_DP = 268;
- // To evenly space the icons, increase the left/right margins for tablets in portrait mode.
- private static final int PORTRAIT_TABLET_LEFT_RIGHT_PADDING_MULTIPLIER = 4;
-
// Workspace
public final int desiredWorkspaceHorizontalMarginOriginalPx;
public int desiredWorkspaceHorizontalMarginPx;
public Point cellLayoutBorderSpaceOriginalPx;
public Point cellLayoutBorderSpacePx;
- public final int cellLayoutPaddingLeftRightPx;
- public final int cellLayoutBottomPaddingPx;
+ public Rect cellLayoutPaddingPx = new Rect();
+
public final int edgeMarginPx;
- public float workspaceSpringLoadShrinkFactor;
+ public float workspaceSpringLoadShrunkTop;
+ public float workspaceSpringLoadShrunkBottom;
public final int workspaceSpringLoadedBottomSpace;
private final int extraSpace;
@@ -161,6 +159,7 @@
public int hotseatBarSizePx;
public int hotseatBarTopPaddingPx;
public final int hotseatBarBottomPaddingPx;
+ public int springLoadedHotseatBarTopMarginPx;
// Start is the side next to the nav bar, end is the side next to the workspace
public final int hotseatBarSidePaddingStartPx;
public final int hotseatBarSidePaddingEndPx;
@@ -206,8 +205,13 @@
// Drop Target
public int dropTargetBarSizePx;
+ public int dropTargetBarTopMarginPx;
+ public int dropTargetBarBottomMarginPx;
public int dropTargetDragPaddingPx;
public int dropTargetTextSizePx;
+ public int dropTargetHorizontalPaddingPx;
+ public int dropTargetVerticalPaddingPx;
+ public int dropTargetGapPx;
// Insets
private final Rect mInsets = new Rect();
@@ -319,23 +323,6 @@
folderCellLayoutBorderSpacePx = new Point(folderCellLayoutBorderSpaceOriginalPx,
folderCellLayoutBorderSpaceOriginalPx);
- int cellLayoutPaddingLeftRightMultiplier = !isVerticalBarLayout() && isTablet
- ? PORTRAIT_TABLET_LEFT_RIGHT_PADDING_MULTIPLIER : 1;
- int cellLayoutPadding = isScalableGrid
- ? 0
- : res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_layout_padding);
-
- if (isTwoPanels) {
- cellLayoutPaddingLeftRightPx = 0;
- cellLayoutBottomPaddingPx = 0;
- } else if (isLandscape) {
- cellLayoutPaddingLeftRightPx = 0;
- cellLayoutBottomPaddingPx = cellLayoutPadding;
- } else {
- cellLayoutPaddingLeftRightPx = cellLayoutPaddingLeftRightMultiplier * cellLayoutPadding;
- cellLayoutBottomPaddingPx = 0;
- }
-
workspacePageIndicatorHeight = res.getDimensionPixelSize(
R.dimen.workspace_page_indicator_height);
mWorkspacePageIndicatorOverlapWorkspace =
@@ -345,8 +332,15 @@
res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
dropTargetBarSizePx = res.getDimensionPixelSize(R.dimen.dynamic_grid_drop_target_size);
+ dropTargetBarTopMarginPx = res.getDimensionPixelSize(R.dimen.drop_target_top_margin);
+ dropTargetBarBottomMarginPx = res.getDimensionPixelSize(R.dimen.drop_target_bottom_margin);
dropTargetDragPaddingPx = res.getDimensionPixelSize(R.dimen.drop_target_drag_padding);
dropTargetTextSizePx = res.getDimensionPixelSize(R.dimen.drop_target_text_size);
+ dropTargetHorizontalPaddingPx = res.getDimensionPixelSize(
+ R.dimen.drop_target_button_drawable_horizontal_padding);
+ dropTargetVerticalPaddingPx = res.getDimensionPixelSize(
+ R.dimen.drop_target_button_drawable_vertical_padding);
+ dropTargetGapPx = res.getDimensionPixelSize(R.dimen.drop_target_button_gap);
workspaceSpringLoadedBottomSpace =
res.getDimensionPixelSize(R.dimen.dynamic_grid_min_spring_loaded_space);
@@ -384,6 +378,8 @@
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
qsbWidth = 0;
}
+ springLoadedHotseatBarTopMarginPx = res.getDimensionPixelSize(
+ R.dimen.spring_loaded_hotseat_top_margin);
hotseatBarSidePaddingEndPx =
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
// Add a bit of space between nav bar and hotseat in vertical bar layout.
@@ -477,6 +473,12 @@
// Recalculate the available dimensions using the new hotseat size.
updateAvailableDimensions(res);
}
+
+ int cellLayoutPadding =
+ isTwoPanels ? cellLayoutBorderSpacePx.x / 2 : res.getDimensionPixelSize(
+ R.dimen.cell_layout_padding);
+ cellLayoutPaddingPx = new Rect(cellLayoutPadding, cellLayoutPadding, cellLayoutPadding,
+ cellLayoutPadding);
updateWorkspacePadding();
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
@@ -589,7 +591,6 @@
float appWidgetScaleX = (float) profile.getCellSize().x / getCellSize().x;
float appWidgetScaleY = (float) profile.getCellSize().y / getCellSize().y;
profile.appWidgetScale.set(appWidgetScaleX, appWidgetScaleY);
- profile.updateWorkspacePadding();
return profile;
}
@@ -624,18 +625,18 @@
}
private void updateAllAppsWidth(Resources res) {
-
+ int cellLayoutHorizontalPadding =
+ (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right) / 2;
if (isTablet) {
- allAppsLeftRightPadding =
- res.getDimensionPixelSize(R.dimen.all_apps_bottom_sheet_horizontal_padding)
- + cellLayoutPaddingLeftRightPx;
+ allAppsLeftRightPadding = res.getDimensionPixelSize(
+ R.dimen.all_apps_bottom_sheet_horizontal_padding) + cellLayoutHorizontalPadding;
int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
+ (allAppsBorderSpacePx.x * (numShownAllAppsColumns + 1))
+ allAppsLeftRightPadding * 2;
allAppsLeftRightMargin = Math.max(1, (availableWidthPx - usedWidth) / 2);
} else {
allAppsLeftRightPadding =
- desiredWorkspaceHorizontalMarginPx + cellLayoutPaddingLeftRightPx;
+ desiredWorkspaceHorizontalMarginPx + cellLayoutHorizontalPadding;
}
}
@@ -645,11 +646,12 @@
private int updateAvailableDimensions(Resources res) {
updateIconSize(1f, res);
+ updateWorkspacePadding();
Point workspacePadding = getTotalWorkspacePadding();
// Check to see if the icons fit within the available height.
float usedHeight = getCellLayoutHeight();
- final int maxHeight = availableHeightPx - workspacePadding.y;
+ final int maxHeight = getWorkspaceHeight(workspacePadding);
float extraHeight = Math.max(0, maxHeight - usedHeight);
float scaleY = maxHeight / usedHeight;
boolean shouldScale = scaleY < 1f;
@@ -659,10 +661,7 @@
// We scale to fit the cellWidth and cellHeight in the available space.
// The benefit of scalable grids is that we can get consistent aspect ratios between
// devices.
- int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
- float usedWidth = (cellWidthPx * numColumns)
- + (cellLayoutBorderSpacePx.x * (numColumns - 1))
- + (desiredWorkspaceHorizontalMarginPx * 2);
+ float usedWidth = getCellLayoutWidth() + (desiredWorkspaceHorizontalMarginPx * 2);
// We do not subtract padding here, as we also scale the workspace padding if needed.
scaleX = availableWidthPx / usedWidth;
shouldScale = true;
@@ -679,7 +678,14 @@
}
private int getCellLayoutHeight() {
- return (cellHeightPx * inv.numRows) + (cellLayoutBorderSpacePx.y * (inv.numRows - 1));
+ return (cellHeightPx * inv.numRows) + (cellLayoutBorderSpacePx.y * (inv.numRows - 1))
+ + cellLayoutPaddingPx.top + cellLayoutPaddingPx.bottom;
+ }
+
+ private int getCellLayoutWidth() {
+ int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
+ return (cellWidthPx * numColumns) + (cellLayoutBorderSpacePx.x * (numColumns - 1))
+ + cellLayoutPaddingPx.left + cellLayoutPaddingPx.right;
}
/**
@@ -739,18 +745,6 @@
}
updateHotseatIconSize(iconSizePx);
- if (!isVerticalLayout) {
- int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx
- - workspacePageIndicatorHeight - edgeMarginPx;
- float minRequiredHeight = dropTargetBarSizePx + workspaceSpringLoadedBottomSpace;
- workspaceSpringLoadShrinkFactor = Math.min(
- res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f,
- 1 - (minRequiredHeight / expectedWorkspaceHeight));
- } else {
- workspaceSpringLoadShrinkFactor =
- res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f;
- }
-
// Folder icon
folderIconSizePx = IconNormalizer.getNormalizedCircleSize(iconSizePx);
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
@@ -851,7 +845,6 @@
public void updateInsets(Rect insets) {
mInsets.set(insets);
- updateWorkspacePadding();
}
/**
@@ -878,23 +871,62 @@
int numColumns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
int screenWidthPx = getWorkspaceWidth(padding);
result.x = calculateCellWidth(screenWidthPx, cellLayoutBorderSpacePx.x, numColumns);
- result.y = calculateCellHeight(availableHeightPx - padding.y
- - cellLayoutBottomPaddingPx, cellLayoutBorderSpacePx.y, inv.numRows);
+ int screenHeightPx = getWorkspaceHeight(padding);
+ result.y = calculateCellHeight(screenHeightPx, cellLayoutBorderSpacePx.y, inv.numRows);
return result;
}
+ /**
+ * Gets the space in px from the bottom of last item in the vertical-bar hotseat to the
+ * bottom of the screen.
+ */
+ public int getVerticalHotseatLastItemBottomOffset() {
+ int cellHeight = calculateCellHeight(
+ heightPx - mHotseatPadding.top - mHotseatPadding.bottom, hotseatBorderSpace,
+ numShownHotseatIcons);
+ int hotseatSize = (cellHeight * numShownHotseatIcons)
+ + (hotseatBorderSpace * (numShownHotseatIcons - 1));
+ int extraHotseatEndSpacing = (heightPx - hotseatSize) / 2;
+ int extraIconEndSpacing = (cellHeight - iconSizePx) / 2;
+ return extraHotseatEndSpacing + extraIconEndSpacing + mHotseatPadding.bottom;
+ }
+
+ /**
+ * Gets the scaled top of the workspace in px for the spring-loaded edit state.
+ */
+ public float getWorkspaceSpringLoadShrunkTop() {
+ workspaceSpringLoadShrunkTop = mInsets.top + dropTargetBarTopMarginPx + dropTargetBarSizePx
+ + dropTargetBarBottomMarginPx;
+ return workspaceSpringLoadShrunkTop;
+ }
+
+ /**
+ * Gets the scaled bottom of the workspace in px for the spring-loaded edit state.
+ */
+ public float getWorkspaceSpringLoadShrunkBottom() {
+ int topOfHotseat = hotseatBarSizePx + springLoadedHotseatBarTopMarginPx;
+ workspaceSpringLoadShrunkBottom =
+ heightPx - (isVerticalBarLayout() ? getVerticalHotseatLastItemBottomOffset()
+ : topOfHotseat);
+ return workspaceSpringLoadShrunkBottom;
+ }
+
public int getWorkspaceWidth() {
return getWorkspaceWidth(getTotalWorkspacePadding());
}
public int getWorkspaceWidth(Point workspacePadding) {
int cellLayoutTotalPadding =
- isTwoPanels ? 4 * cellLayoutPaddingLeftRightPx : 2 * cellLayoutPaddingLeftRightPx;
+ (isTwoPanels ? 2 : 1) * (cellLayoutPaddingPx.left + cellLayoutPaddingPx.right);
return availableWidthPx - workspacePadding.x - cellLayoutTotalPadding;
}
+ private int getWorkspaceHeight(Point workspacePadding) {
+ return availableHeightPx - workspacePadding.y - (cellLayoutPaddingPx.top
+ + cellLayoutPaddingPx.bottom);
+ }
+
public Point getTotalWorkspacePadding() {
- updateWorkspacePadding();
return new Point(workspacePadding.left + workspacePadding.right,
workspacePadding.top + workspacePadding.bottom);
}
@@ -920,12 +952,26 @@
int hotseatTop = hotseatBarSizePx;
int paddingBottom = hotseatTop + workspacePageIndicatorHeight
+ workspaceBottomPadding - mWorkspacePageIndicatorOverlapWorkspace;
+ int paddingTop = workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx);
+ int paddingSide = desiredWorkspaceHorizontalMarginPx;
- padding.set(desiredWorkspaceHorizontalMarginPx,
- workspaceTopPadding + (isScalableGrid ? 0 : edgeMarginPx),
- desiredWorkspaceHorizontalMarginPx,
- paddingBottom);
+ padding.set(paddingSide, paddingTop, paddingSide, paddingBottom);
}
+ insetPadding(workspacePadding, cellLayoutPaddingPx);
+ }
+
+ private void insetPadding(Rect paddings, Rect insets) {
+ insets.left = Math.min(insets.left, paddings.left);
+ paddings.left -= insets.left;
+
+ insets.top = Math.min(insets.top, paddings.top);
+ paddings.top -= insets.top;
+
+ insets.right = Math.min(insets.right, paddings.right);
+ paddings.right -= insets.right;
+
+ insets.bottom = Math.min(insets.bottom, paddings.bottom);
+ paddings.bottom -= insets.bottom;
}
/**
@@ -933,12 +979,14 @@
*/
public Rect getHotseatLayoutPadding(Context context) {
if (isVerticalBarLayout()) {
+ int paddingTop = Math.max(mInsets.top - cellLayoutPaddingPx.top, 0);
+ int paddingBottom = Math.max(mInsets.bottom - cellLayoutPaddingPx.bottom, 0);
if (isSeascape()) {
- mHotseatPadding.set(mInsets.left + hotseatBarSidePaddingStartPx,
- mInsets.top, hotseatBarSidePaddingEndPx, mInsets.bottom);
+ mHotseatPadding.set(mInsets.left + hotseatBarSidePaddingStartPx, paddingTop,
+ hotseatBarSidePaddingEndPx, paddingBottom);
} else {
- mHotseatPadding.set(hotseatBarSidePaddingEndPx, mInsets.top,
- mInsets.right + hotseatBarSidePaddingStartPx, mInsets.bottom);
+ mHotseatPadding.set(hotseatBarSidePaddingEndPx, paddingTop,
+ mInsets.right + hotseatBarSidePaddingStartPx, paddingBottom);
}
} else if (isTaskbarPresent) {
int hotseatHeight = workspacePadding.bottom;
@@ -977,14 +1025,12 @@
float workspaceCellWidth = (float) widthPx / inv.numColumns;
float hotseatCellWidth = (float) widthPx / numShownHotseatIcons;
int hotseatAdjustment = Math.round((workspaceCellWidth - hotseatCellWidth) / 2);
- mHotseatPadding.set(
- hotseatAdjustment + workspacePadding.left + cellLayoutPaddingLeftRightPx
- + mInsets.left,
- hotseatBarTopPaddingPx,
- hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx
+ mHotseatPadding.set(hotseatAdjustment + workspacePadding.left + cellLayoutPaddingPx.left
+ + mInsets.left, hotseatBarTopPaddingPx,
+ hotseatAdjustment + workspacePadding.right + cellLayoutPaddingPx.right
+ mInsets.right,
hotseatBarSizePx - hotseatCellHeightPx - hotseatBarTopPaddingPx
- + cellLayoutBottomPaddingPx + mInsets.bottom);
+ + mInsets.bottom);
}
return mHotseatPadding;
}
@@ -1068,6 +1114,8 @@
.getInfo().rotation == Surface.ROTATION_270;
if (mIsSeascape != isSeascape) {
mIsSeascape = isSeascape;
+ // Hotseat changing sides requires updating workspace left/right paddings
+ updateWorkspacePadding();
return true;
}
}
@@ -1146,6 +1194,11 @@
cellLayoutBorderSpacePx.x));
writer.println(prefix + pxToDpStr("cellLayoutBorderSpacePx Vertical",
cellLayoutBorderSpacePx.y));
+ writer.println(prefix + pxToDpStr("cellLayoutPaddingPx.left", cellLayoutPaddingPx.left));
+ writer.println(prefix + pxToDpStr("cellLayoutPaddingPx.top", cellLayoutPaddingPx.top));
+ writer.println(prefix + pxToDpStr("cellLayoutPaddingPx.right", cellLayoutPaddingPx.right));
+ writer.println(
+ prefix + pxToDpStr("cellLayoutPaddingPx.bottom", cellLayoutPaddingPx.bottom));
writer.println(prefix + pxToDpStr("iconSizePx", iconSizePx));
writer.println(prefix + pxToDpStr("iconTextSizePx", iconTextSizePx));
@@ -1182,6 +1235,12 @@
hotseatBarSidePaddingStartPx));
writer.println(prefix + pxToDpStr("hotseatBarSidePaddingEndPx",
hotseatBarSidePaddingEndPx));
+ writer.println(prefix + pxToDpStr("springLoadedHotseatBarTopMarginPx",
+ springLoadedHotseatBarTopMarginPx));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.top", mHotseatPadding.top));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.bottom", mHotseatPadding.bottom));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.left", mHotseatPadding.left));
+ writer.println(prefix + pxToDpStr("mHotseatPadding.right", mHotseatPadding.right));
writer.println(prefix + "\tnumShownHotseatIcons: " + numShownHotseatIcons);
writer.println(prefix + pxToDpStr("hotseatBorderSpace", hotseatBorderSpace));
writer.println(prefix + "\tisQsbInline: " + isQsbInline);
@@ -1232,6 +1291,16 @@
writer.println(prefix + pxToDpStr("overviewPageSpacing", overviewPageSpacing));
writer.println(prefix + pxToDpStr("overviewRowSpacing", overviewRowSpacing));
writer.println(prefix + pxToDpStr("overviewGridSideMargin", overviewGridSideMargin));
+
+ writer.println(prefix + pxToDpStr("dropTargetBarTopMarginPx", dropTargetBarTopMarginPx));
+ writer.println(prefix + pxToDpStr("dropTargetBarSizePx", dropTargetBarSizePx));
+ writer.println(
+ prefix + pxToDpStr("dropTargetBarBottomMarginPx", dropTargetBarBottomMarginPx));
+
+ writer.println(
+ prefix + pxToDpStr("workspaceSpringLoadShrunkTop", workspaceSpringLoadShrunkTop));
+ writer.println(prefix + pxToDpStr("workspaceSpringLoadShrunkBottom",
+ workspaceSpringLoadShrunkBottom));
}
private static Context getContext(Context c, Info info, int orientation, WindowBounds bounds) {
diff --git a/src/com/android/launcher3/DropTargetBar.java b/src/com/android/launcher3/DropTargetBar.java
index 9fb14f6..73289fb 100644
--- a/src/com/android/launcher3/DropTargetBar.java
+++ b/src/com/android/launcher3/DropTargetBar.java
@@ -17,8 +17,6 @@
package com.android.launcher3;
import static com.android.launcher3.ButtonDropTarget.TOOLTIP_DEFAULT;
-import static com.android.launcher3.ButtonDropTarget.TOOLTIP_LEFT;
-import static com.android.launcher3.ButtonDropTarget.TOOLTIP_RIGHT;
import static com.android.launcher3.anim.AlphaUpdateListener.updateVisibility;
import android.animation.TimeInterpolator;
@@ -41,6 +39,8 @@
import com.android.launcher3.dragndrop.DragOptions;
import com.android.launcher3.testing.TestProtocol;
+import java.util.Arrays;
+
/*
* The top bar containing various drop targets: Delete/App Info/Uninstall.
*/
@@ -94,30 +94,28 @@
lp.rightMargin = insets.right;
int tooltipLocation = TOOLTIP_DEFAULT;
- if (grid.isVerticalBarLayout()) {
- lp.width = grid.dropTargetBarSizePx;
- lp.height = grid.availableHeightPx - 2 * grid.edgeMarginPx;
- lp.gravity = grid.isSeascape() ? Gravity.RIGHT : Gravity.LEFT;
- tooltipLocation = grid.isSeascape() ? TOOLTIP_LEFT : TOOLTIP_RIGHT;
+ int horizontalMargin;
+ if (grid.isTablet) {
+ // XXX: If the icon size changes across orientations, we will have to take
+ // that into account here too.
+ horizontalMargin = ((grid.widthPx - 2 * grid.edgeMarginPx
+ - (grid.inv.numColumns * grid.cellWidthPx))
+ / (2 * (grid.inv.numColumns + 1)))
+ + grid.edgeMarginPx;
} else {
- int gap;
- if (grid.isTablet) {
- // XXX: If the icon size changes across orientations, we will have to take
- // that into account here too.
- gap = ((grid.widthPx - 2 * grid.edgeMarginPx
- - (grid.inv.numColumns * grid.cellWidthPx))
- / (2 * (grid.inv.numColumns + 1)))
- + grid.edgeMarginPx;
- } else {
- gap = getContext().getResources()
- .getDimensionPixelSize(R.dimen.drop_target_bar_margin_horizontal);
- }
- lp.width = grid.availableWidthPx - 2 * gap;
-
- lp.topMargin += grid.edgeMarginPx;
- lp.height = grid.dropTargetBarSizePx;
- lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
+ horizontalMargin = getContext().getResources()
+ .getDimensionPixelSize(R.dimen.drop_target_bar_margin_horizontal);
}
+ lp.topMargin += grid.dropTargetBarTopMarginPx;
+ lp.bottomMargin += grid.dropTargetBarBottomMarginPx;
+ lp.width = grid.availableWidthPx - 2 * horizontalMargin;
+ if (mIsVertical) {
+ lp.leftMargin = (grid.widthPx - lp.width) / 2;
+ lp.rightMargin = (grid.widthPx - lp.width) / 2;
+ }
+ lp.height = grid.dropTargetBarSizePx;
+ lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP;
+
setLayoutParams(lp);
for (ButtonDropTarget button : mDropTargets) {
button.setTextSize(TypedValue.COMPLEX_UNIT_PX, grid.dropTargetTextSizePx);
@@ -139,19 +137,7 @@
int height = MeasureSpec.getSize(heightMeasureSpec);
int visibleCount = getVisibleButtonsCount();
- if (visibleCount == 0) {
- // do nothing
- } else if (mIsVertical) {
- int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
- int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
-
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- button.setTextVisible(false);
- button.measure(widthSpec, heightSpec);
- }
- }
- } else {
+ if (visibleCount > 0) {
int availableWidth = width / visibleCount;
boolean textVisible = true;
for (ButtonDropTarget buttons : mDropTargets) {
@@ -176,31 +162,91 @@
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int visibleCount = getVisibleButtonsCount();
if (visibleCount == 0) {
- // do nothing
- } else if (mIsVertical) {
- int gap = getResources().getDimensionPixelSize(R.dimen.drop_target_vertical_gap);
- int start = gap;
- int end;
+ return;
+ }
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- end = start + button.getMeasuredHeight();
- button.layout(0, start, button.getMeasuredWidth(), end);
- start = end + gap;
- }
- }
- } else {
- int frameSize = (right - left) / visibleCount;
+ Launcher launcher = Launcher.getLauncher(getContext());
+ Workspace workspace = launcher.getWorkspace();
+ DeviceProfile dp = launcher.getDeviceProfile();
+ int buttonHorizontalPadding = dp.dropTargetHorizontalPaddingPx;
+ int buttonVerticalPadding = dp.dropTargetVerticalPaddingPx;
+ int barCenter = (right - left) / 2;
- int start = frameSize / 2;
- int halfWidth;
- for (ButtonDropTarget button : mDropTargets) {
- if (button.getVisibility() != GONE) {
- halfWidth = button.getMeasuredWidth() / 2;
- button.layout(start - halfWidth, 0,
- start + halfWidth, button.getMeasuredHeight());
- start = start + frameSize;
+ ButtonDropTarget[] visibleButtons = Arrays.stream(mDropTargets)
+ .filter(b -> b.getVisibility() != GONE)
+ .toArray(ButtonDropTarget[]::new);
+ Arrays.stream(visibleButtons).forEach(
+ b -> b.setPadding(buttonHorizontalPadding, buttonVerticalPadding,
+ buttonHorizontalPadding, buttonVerticalPadding));
+
+ if (visibleCount == 1) {
+ ButtonDropTarget button = visibleButtons[0];
+ button.layout(barCenter - (button.getMeasuredWidth() / 2), 0,
+ barCenter + (button.getMeasuredWidth() / 2), button.getMeasuredHeight());
+ } else if (visibleCount == 2) {
+ int buttonGap = dp.dropTargetGapPx;
+
+ if (dp.isTwoPanels) {
+ ButtonDropTarget leftButton = visibleButtons[0];
+ leftButton.layout(barCenter - leftButton.getMeasuredWidth() - (buttonGap / 2), 0,
+ barCenter - (buttonGap / 2), leftButton.getMeasuredHeight());
+
+ ButtonDropTarget rightButton = visibleButtons[1];
+ rightButton.layout(barCenter + (buttonGap / 2), 0,
+ barCenter + rightButton.getMeasuredWidth() + (buttonGap / 2),
+ rightButton.getMeasuredHeight());
+ } else if (dp.isTablet) {
+ int numberOfMargins = visibleCount - 1;
+ int buttonWidths = Arrays.stream(mDropTargets)
+ .filter(b -> b.getVisibility() != GONE)
+ .mapToInt(ButtonDropTarget::getMeasuredWidth)
+ .sum();
+ int totalWidth = buttonWidths + (numberOfMargins * buttonGap);
+ int buttonsStartMargin = barCenter - (totalWidth / 2);
+
+ int start = buttonsStartMargin;
+ for (ButtonDropTarget button : visibleButtons) {
+ int margin = (start != buttonsStartMargin) ? buttonGap : 0;
+ button.layout(start + margin, 0, start + margin + button.getMeasuredWidth(),
+ button.getMeasuredHeight());
+ start += button.getMeasuredWidth() + margin;
}
+ } else if (mIsVertical) {
+ // Center buttons over workspace, not screen.
+ int verticalCenter = (workspace.getRight() - workspace.getLeft()) / 2;
+ ButtonDropTarget leftButton = visibleButtons[0];
+ leftButton.layout(verticalCenter - leftButton.getMeasuredWidth() - (buttonGap / 2),
+ 0, verticalCenter - (buttonGap / 2), leftButton.getMeasuredHeight());
+
+ ButtonDropTarget rightButton = visibleButtons[1];
+ rightButton.layout(verticalCenter + (buttonGap / 2), 0,
+ verticalCenter + rightButton.getMeasuredWidth() + (buttonGap / 2),
+ rightButton.getMeasuredHeight());
+ } else if (dp.isPhone) {
+ // Buttons aligned to outer edges of scaled workspace.
+ float shrunkTop = dp.getWorkspaceSpringLoadShrunkTop();
+ float shrunkBottom = dp.getWorkspaceSpringLoadShrunkBottom();
+ float scale =
+ (shrunkBottom - shrunkTop) / launcher.getWorkspace().getNormalChildHeight();
+ int workspaceWidth = (int) (launcher.getWorkspace().getNormalChildWidth() * scale);
+ int start = barCenter - (workspaceWidth / 2);
+ int end = barCenter + (workspaceWidth / 2);
+
+ ButtonDropTarget leftButton = visibleButtons[0];
+ ButtonDropTarget rightButton = visibleButtons[1];
+
+ // If the text within the buttons is too long, the buttons can overlap
+ int overlap = start + leftButton.getMeasuredWidth() + rightButton.getMeasuredWidth()
+ - end;
+ if (overlap > 0) {
+ start -= overlap / 2;
+ end += overlap / 2;
+ }
+
+ leftButton.layout(start, 0, start + leftButton.getMeasuredWidth(),
+ leftButton.getMeasuredHeight());
+ rightButton.layout(end - rightButton.getMeasuredWidth(), 0, end,
+ rightButton.getMeasuredHeight());
}
}
}
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index 2c14f07..1eb493b 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -775,7 +775,7 @@
pageScrollChanged = true;
outPageScrolls[i] = pageScroll;
}
- childStart += primaryDimension + getChildGap();
+ childStart += primaryDimension + getChildGap(i, i + delta);
// This makes sure that the space is added after the page, not after each panel
int lastPanel = mIsRtl ? 0 : panelCount - 1;
@@ -799,7 +799,7 @@
return pageScrollChanged;
}
- protected int getChildGap() {
+ protected int getChildGap(int fromIndex, int toIndex) {
return 0;
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 8b19a19..a7fc2f5 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -324,37 +324,14 @@
setPageSpacing(Math.max(maxInsets, maxPadding));
}
- updateWorkspaceScreensPadding();
+ updateCellLayoutPadding();
updateWorkspaceWidgetsSizes();
}
- private void updateWorkspaceScreensPadding() {
- DeviceProfile grid = mLauncher.getDeviceProfile();
- int paddingLeftRight = grid.cellLayoutPaddingLeftRightPx;
- int paddingBottom = grid.cellLayoutBottomPaddingPx;
-
- int panelCount = getPanelCount();
- int rightPanelModulus = mIsRtl ? 0 : panelCount - 1;
- int leftPanelModulus = mIsRtl ? panelCount - 1 : 0;
- int numberOfScreens = mScreenOrder.size();
- for (int i = 0; i < numberOfScreens; i++) {
- int paddingLeft = paddingLeftRight;
- int paddingRight = paddingLeftRight;
- // Add missing cellLayout border in-between panels.
- if (panelCount > 1) {
- if (i % panelCount == leftPanelModulus) {
- paddingRight += grid.cellLayoutBorderSpacePx.x / 2;
- } else if (i % panelCount == rightPanelModulus) { // right side panel
- paddingLeft += grid.cellLayoutBorderSpacePx.x / 2;
- } else { // middle panel
- paddingLeft += grid.cellLayoutBorderSpacePx.x / 2;
- paddingRight += grid.cellLayoutBorderSpacePx.x / 2;
- }
- }
- // SparseArrayMap doesn't keep the order
- mWorkspaceScreens.get(mScreenOrder.get(i))
- .setPadding(paddingLeft, 0, paddingRight, paddingBottom);
- }
+ private void updateCellLayoutPadding() {
+ Rect padding = mLauncher.getDeviceProfile().cellLayoutPaddingPx;
+ mWorkspaceScreens.forEach(
+ s -> s.setPadding(padding.left, padding.top, padding.right, padding.bottom));
}
private void updateWorkspaceWidgetsSizes() {
@@ -652,7 +629,7 @@
mLauncher.getStateManager().getState(), newScreen, insertIndex);
updatePageScrollValues();
- updateWorkspaceScreensPadding();
+ updateCellLayoutPadding();
return newScreen;
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index de33ae5..8ba2070 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -258,6 +258,9 @@
"ENABLE_NEW_MIGRATION_LOGIC", true,
"Enable the new grid migration logic, keeping pages when src < dest");
+ public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = new DeviceFlag(
+ "ENABLE_ONE_SEARCH_MOTION", false, "Enables animations in OneSearch.");
+
public static void initialize(Context context) {
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java
index 65991e4..3d5aef5 100644
--- a/src/com/android/launcher3/folder/FolderPagedView.java
+++ b/src/com/android/launcher3/folder/FolderPagedView.java
@@ -252,7 +252,7 @@
}
@Override
- protected int getChildGap() {
+ protected int getChildGap(int fromIndex, int toIndex) {
return getPaddingLeft() + getPaddingRight();
}
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index cc17064..3dfece7 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -225,21 +225,21 @@
mHotseat.resetLayout(false);
CellLayout firstScreen = mRootView.findViewById(R.id.workspace);
- firstScreen.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingLeftRightPx,
- mDp.workspacePadding.top,
+ firstScreen.setPadding(mDp.workspacePadding.left + mDp.cellLayoutPaddingPx.left,
+ mDp.workspacePadding.top + mDp.cellLayoutPaddingPx.top,
(mDp.isTwoPanels ? mDp.cellLayoutBorderSpacePx.x / 2
- : mDp.workspacePadding.right) + mDp.cellLayoutPaddingLeftRightPx,
- mDp.workspacePadding.bottom
+ : mDp.workspacePadding.right) + mDp.cellLayoutPaddingPx.right,
+ mDp.workspacePadding.bottom + mDp.cellLayoutPaddingPx.bottom
);
mWorkspaceScreens.put(FIRST_SCREEN_ID, firstScreen);
if (mDp.isTwoPanels) {
CellLayout rightPanel = mRootView.findViewById(R.id.workspace_right);
rightPanel.setPadding(
- mDp.cellLayoutBorderSpacePx.x / 2 + mDp.cellLayoutPaddingLeftRightPx,
- mDp.workspacePadding.top,
- mDp.workspacePadding.right + mDp.cellLayoutPaddingLeftRightPx,
- mDp.workspacePadding.bottom
+ mDp.cellLayoutBorderSpacePx.x / 2 + mDp.cellLayoutPaddingPx.left,
+ mDp.workspacePadding.top + mDp.cellLayoutPaddingPx.top,
+ mDp.workspacePadding.right + mDp.cellLayoutPaddingPx.right,
+ mDp.workspacePadding.bottom + mDp.cellLayoutPaddingPx.bottom
);
mWorkspaceScreens.put(Workspace.SECOND_SCREEN_ID, rightPanel);
}
diff --git a/src/com/android/launcher3/icons/IconCache.java b/src/com/android/launcher3/icons/IconCache.java
index 5ece4a6..7ba2317 100644
--- a/src/com/android/launcher3/icons/IconCache.java
+++ b/src/com/android/launcher3/icons/IconCache.java
@@ -16,6 +16,7 @@
package com.android.launcher3.icons;
+import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
@@ -340,14 +341,15 @@
Map<Pair<UserHandle, Boolean>, List<IconRequestInfo<T>>> iconLoadSubsectionsMap =
iconRequestInfos.stream()
.filter(iconRequest -> {
- if (iconRequest.itemInfo.getTargetComponent() != null) {
- return true;
+ if (iconRequest.itemInfo.getTargetComponent() == null) {
+ Log.i(TAG,
+ "Skipping Item info with null component name: "
+ + iconRequest.itemInfo);
+ iconRequest.itemInfo.bitmap = getDefaultIcon(
+ iconRequest.itemInfo.user);
+ return false;
}
- Log.i(TAG,
- "Skipping Item info with null component name: "
- + iconRequest.itemInfo);
- iconRequest.itemInfo.bitmap = getDefaultIcon(iconRequest.itemInfo.user);
- return false;
+ return true;
})
.collect(groupingBy(iconRequest ->
Pair.create(iconRequest.itemInfo.user, iconRequest.useLowResIcon)));
@@ -356,6 +358,17 @@
iconLoadSubsectionsMap.forEach((sectionKey, filteredList) -> {
Map<ComponentName, List<IconRequestInfo<T>>> duplicateIconRequestsMap =
filteredList.stream()
+ .filter(iconRequest -> {
+ // Filter out icons that should not share the same bitmap and title
+ if (iconRequest.itemInfo.itemType == ITEM_TYPE_DEEP_SHORTCUT) {
+ Log.e(TAG,
+ "Skipping Item info for deep shortcut: "
+ + iconRequest.itemInfo,
+ new IllegalStateException());
+ return false;
+ }
+ return true;
+ })
.collect(groupingBy(iconRequest ->
iconRequest.itemInfo.getTargetComponent()));
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index b9fa21d..f1c5d59 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -615,7 +615,13 @@
}
if (info != null) {
- iconRequestInfos.add(c.createIconRequestInfo(info, useLowResIcon));
+ if (info.itemType
+ != LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
+ // Skip deep shortcuts; their title and icons have already been
+ // loaded above.
+ iconRequestInfos.add(
+ c.createIconRequestInfo(info, useLowResIcon));
+ }
c.applyCommonProperties(info);
diff --git a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
index 967f2c8..9201006 100644
--- a/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
+++ b/src/com/android/launcher3/secondarydisplay/SecondaryDragLayer.java
@@ -113,13 +113,17 @@
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child == mAppsView) {
- int padding = 2 * (grid.desiredWorkspaceHorizontalMarginPx
- + grid.cellLayoutPaddingLeftRightPx);
+ int horizontalPadding = (2 * grid.desiredWorkspaceHorizontalMarginPx)
+ + grid.cellLayoutPaddingPx.left + grid.cellLayoutPaddingPx.right;
+ int verticalPadding =
+ grid.cellLayoutPaddingPx.top + grid.cellLayoutPaddingPx.bottom;
- int maxWidth = grid.allAppsCellWidthPx * grid.numShownAllAppsColumns + padding;
+ int maxWidth =
+ grid.allAppsCellWidthPx * grid.numShownAllAppsColumns + horizontalPadding;
int appsWidth = Math.min(width, maxWidth);
- int maxHeight = grid.allAppsCellHeightPx * grid.numShownAllAppsColumns + padding;
+ int maxHeight =
+ grid.allAppsCellHeightPx * grid.numShownAllAppsColumns + verticalPadding;
int appsHeight = Math.min(height, maxHeight);
mAppsView.measure(
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index d52594e..9be3cc5 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -18,7 +18,6 @@
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import android.content.Context;
-import android.graphics.Rect;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
@@ -52,28 +51,15 @@
return super.getWorkspaceScaleAndTranslation(launcher);
}
- if (grid.isVerticalBarLayout()) {
- float scale = grid.workspaceSpringLoadShrinkFactor;
- return new ScaleAndTranslation(scale, 0, 0);
- }
-
- float scale = grid.workspaceSpringLoadShrinkFactor;
- Rect insets = launcher.getDragLayer().getInsets();
-
- float scaledHeight = scale * ws.getNormalChildHeight();
- float shrunkTop = insets.top + grid.dropTargetBarSizePx;
- float shrunkBottom = ws.getMeasuredHeight() - insets.bottom
- - grid.workspacePadding.bottom
- - grid.workspaceSpringLoadedBottomSpace;
- float totalShrunkSpace = shrunkBottom - shrunkTop;
-
- float desiredCellTop = shrunkTop + (totalShrunkSpace - scaledHeight) / 2;
+ float shrunkTop = grid.getWorkspaceSpringLoadShrunkTop();
+ float shrunkBottom = grid.getWorkspaceSpringLoadShrunkBottom();
+ float scale = (shrunkBottom - shrunkTop) / ws.getNormalChildHeight();
float halfHeight = ws.getHeight() / 2;
float myCenter = ws.getTop() + halfHeight;
float cellTopFromCenter = halfHeight - ws.getChildAt(0).getTop();
float actualCellTop = myCenter - cellTopFromCenter * scale;
- return new ScaleAndTranslation(scale, 0, (desiredCellTop - actualCellTop) / scale);
+ return new ScaleAndTranslation(scale, 0, (shrunkTop - actualCellTop) / scale);
}
@Override
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 2609e54..217a558 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -16,6 +16,7 @@
package com.android.launcher3.touch;
+import static android.view.Gravity.BOTTOM;
import static android.view.Gravity.CENTER_VERTICAL;
import static android.view.Gravity.END;
import static android.view.Gravity.START;
@@ -414,14 +415,17 @@
@Override
public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
StagedSplitBounds splitInfo, int desiredStagePosition) {
- float diff;
- float horizontalDividerDiff = splitInfo.visualDividerBounds.width() / 2f;
+ float topLeftTaskPercent = splitInfo.appsStackedVertically
+ ? splitInfo.topTaskPercent
+ : splitInfo.leftTaskPercent;
+ float dividerBarPercent = splitInfo.appsStackedVertically
+ ? splitInfo.dividerHeightPercent
+ : splitInfo.dividerWidthPercent;
+
if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
- diff = outRect.height() * (1f - splitInfo.leftTaskPercent) + horizontalDividerDiff;
- outRect.bottom -= diff;
+ outRect.bottom = outRect.top + (int) (outRect.height() * topLeftTaskPercent);
} else {
- diff = outRect.height() * splitInfo.leftTaskPercent + horizontalDividerDiff;
- outRect.top += diff;
+ outRect.top += (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent));
}
}
@@ -468,18 +472,42 @@
@Override
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
- boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+ int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+ DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
FrameLayout.LayoutParams primaryIconParams =
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
FrameLayout.LayoutParams secondaryIconParams =
new FrameLayout.LayoutParams(primaryIconParams);
- primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END);
+ // We calculate the "midpoint" of the thumbnail area, and place the icons there.
+ // This is the place where the thumbnail area splits by default, in a near-50/50 split.
+ // It is usually not exactly 50/50, due to insets/screen cutouts.
+ int fullscreenInsetThickness = deviceProfile.getInsets().top;
+ int fullscreenMidpointFromBottom = ((deviceProfile.heightPx - fullscreenInsetThickness)
+ / 2);
+ float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
+ float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
+ int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
+ int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
+ int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
+ int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
+
+ primaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
+ secondaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
primaryIconView.setTranslationX(0);
- primaryIconView.setTranslationY(-(taskIconHeight / 2f));
- secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END);
secondaryIconView.setTranslationX(0);
- secondaryIconView.setTranslationY(taskIconHeight / 2f);
+ if (splitConfig.initiatedFromSeascape) {
+ // if the split was initiated from seascape,
+ // the task on the right (secondary) is slightly larger
+ primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
+ secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
+ + taskIconHeight);
+ } else {
+ // if not,
+ // the task on the left (primary) is slightly larger
+ primaryIconView.setTranslationY(-bottomToMidpointOffset);
+ secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
+ }
primaryIconView.setLayoutParams(primaryIconParams);
secondaryIconView.setLayoutParams(secondaryIconParams);
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 6e594e9..1b17126 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -146,7 +146,8 @@
int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl);
void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
- boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
+ int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+ DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
/*
* The following two methods try to center the TaskMenuView in landscape by finding the center
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 2c9afd6..7e1cb25 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -18,6 +18,7 @@
import static android.view.Gravity.BOTTOM;
import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.Gravity.END;
import static android.view.Gravity.START;
import static android.view.Gravity.TOP;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -334,8 +335,14 @@
// Set translations
if (deviceProfile.isLandscape) {
if (desiredTaskId == splitBounds.rightBottomTaskId) {
- translationX = ((taskViewWidth * splitBounds.leftTaskPercent)
- + (taskViewWidth * splitBounds.dividerWidthPercent));
+ float leftTopTaskPercent = splitBounds.appsStackedVertically
+ ? splitBounds.topTaskPercent
+ : splitBounds.leftTaskPercent;
+ float dividerThicknessPercent = splitBounds.appsStackedVertically
+ ? splitBounds.dividerHeightPercent
+ : splitBounds.dividerWidthPercent;
+ translationX = ((taskViewWidth * leftTopTaskPercent)
+ + (taskViewWidth * dividerThicknessPercent));
}
} else {
if (desiredTaskId == splitBounds.leftTopTaskId) {
@@ -488,19 +495,24 @@
public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
StagedSplitBounds splitInfo, int desiredStagePosition) {
boolean isLandscape = dp.isLandscape;
+ float topLeftTaskPercent = splitInfo.appsStackedVertically
+ ? splitInfo.topTaskPercent
+ : splitInfo.leftTaskPercent;
+ float dividerBarPercent = splitInfo.appsStackedVertically
+ ? splitInfo.dividerHeightPercent
+ : splitInfo.dividerWidthPercent;
+
if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
if (isLandscape) {
- outRect.right = outRect.left + (int) (outRect.width() * splitInfo.leftTaskPercent);
+ outRect.right = outRect.left + (int) (outRect.width() * topLeftTaskPercent);
} else {
- outRect.bottom = outRect.top + (int) (outRect.height() * splitInfo.topTaskPercent);
+ outRect.bottom = outRect.top + (int) (outRect.height() * topLeftTaskPercent);
}
} else {
if (isLandscape) {
- outRect.left += (int) (outRect.width() *
- (splitInfo.leftTaskPercent + splitInfo.dividerWidthPercent));
+ outRect.left += (int) (outRect.width() * (topLeftTaskPercent + dividerBarPercent));
} else {
- outRect.top += (int) (outRect.height() *
- (splitInfo.topTaskPercent + splitInfo.dividerHeightPercent));
+ outRect.top += (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent));
}
}
}
@@ -559,18 +571,70 @@
@Override
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
- boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+ int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+ DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
FrameLayout.LayoutParams primaryIconParams =
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
FrameLayout.LayoutParams secondaryIconParams =
new FrameLayout.LayoutParams(primaryIconParams);
- primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
- // shifts icon half a width left (height is used conveniently here since icons are square)
- primaryIconView.setTranslationX(-(taskIconHeight / 2f));
+ if (deviceProfile.isLandscape) {
+ // We calculate the "midpoint" of the thumbnail area, and place the icons there.
+ // This is the place where the thumbnail area splits by default, in a near-50/50 split.
+ // It is usually not exactly 50/50, due to insets/screen cutouts.
+ int fullscreenInsetThickness = deviceProfile.isSeascape()
+ ? deviceProfile.getInsets().right
+ : deviceProfile.getInsets().left;
+ int fullscreenMidpointFromBottom = ((deviceProfile.widthPx
+ - fullscreenInsetThickness) / 2);
+ float midpointFromBottomPct = (float) fullscreenMidpointFromBottom
+ / deviceProfile.widthPx;
+ float insetPct = (float) fullscreenInsetThickness / deviceProfile.widthPx;
+ int spaceAboveSnapshots = 0;
+ int overviewThumbnailAreaThickness = groupedTaskViewWidth - spaceAboveSnapshots;
+ int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness
+ * midpointFromBottomPct);
+ int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
+
+ if (deviceProfile.isSeascape()) {
+ primaryIconParams.gravity = TOP | (isRtl ? END : START);
+ secondaryIconParams.gravity = TOP | (isRtl ? END : START);
+ if (splitConfig.initiatedFromSeascape) {
+ // if the split was initiated from seascape,
+ // the task on the right (secondary) is slightly larger
+ primaryIconView.setTranslationX(bottomToMidpointOffset - taskIconHeight);
+ secondaryIconView.setTranslationX(bottomToMidpointOffset);
+ } else {
+ // if not,
+ // the task on the left (primary) is slightly larger
+ primaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset
+ - taskIconHeight);
+ secondaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset);
+ }
+ } else {
+ primaryIconParams.gravity = TOP | (isRtl ? START : END);
+ secondaryIconParams.gravity = TOP | (isRtl ? START : END);
+ if (!splitConfig.initiatedFromSeascape) {
+ // if the split was initiated from landscape,
+ // the task on the left (primary) is slightly larger
+ primaryIconView.setTranslationX(-bottomToMidpointOffset);
+ secondaryIconView.setTranslationX(-bottomToMidpointOffset + taskIconHeight);
+ } else {
+ // if not,
+ // the task on the right (secondary) is slightly larger
+ primaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset);
+ secondaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset
+ + taskIconHeight);
+ }
+ }
+ } else {
+ primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
+ // shifts icon half a width left (height is used here since icons are square)
+ primaryIconView.setTranslationX(-(taskIconHeight / 2f));
+ secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
+ secondaryIconView.setTranslationX(taskIconHeight / 2f);
+ }
primaryIconView.setTranslationY(0);
- secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
- secondaryIconView.setTranslationX(taskIconHeight / 2f);
secondaryIconView.setTranslationY(0);
primaryIconView.setLayoutParams(primaryIconParams);
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index 9151796..74b6a5b 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -178,16 +178,46 @@
@Override
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
- boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+ int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+ DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
super.setSplitIconParams(primaryIconView, secondaryIconView, taskIconHeight,
- primarySnapshotWidth, primarySnapshotHeight, isRtl, deviceProfile, splitConfig);
+ primarySnapshotWidth, primarySnapshotHeight, groupedTaskViewHeight,
+ groupedTaskViewWidth, isRtl, deviceProfile, splitConfig);
FrameLayout.LayoutParams primaryIconParams =
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
FrameLayout.LayoutParams secondaryIconParams =
(FrameLayout.LayoutParams) secondaryIconView.getLayoutParams();
- primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START);
- secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START);
+ // We calculate the "midpoint" of the thumbnail area, and place the icons there.
+ // This is the place where the thumbnail area splits by default, in a near-50/50 split.
+ // It is usually not exactly 50/50, due to insets/screen cutouts.
+ int fullscreenInsetThickness = deviceProfile.getInsets().top;
+ int fullscreenMidpointFromBottom = ((deviceProfile.heightPx
+ - fullscreenInsetThickness) / 2);
+ float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
+ float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
+ int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
+ int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
+ int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
+ int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
+
+ primaryIconParams.gravity = BOTTOM | (isRtl ? END : START);
+ secondaryIconParams.gravity = BOTTOM | (isRtl ? END : START);
+ primaryIconView.setTranslationX(0);
+ secondaryIconView.setTranslationX(0);
+ if (splitConfig.initiatedFromSeascape) {
+ // if the split was initiated from seascape,
+ // the task on the right (secondary) is slightly larger
+ primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
+ secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
+ + taskIconHeight);
+ } else {
+ // if not,
+ // the task on the left (primary) is slightly larger
+ primaryIconView.setTranslationY(-bottomToMidpointOffset);
+ secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
+ }
+
primaryIconView.setLayoutParams(primaryIconParams);
secondaryIconView.setLayoutParams(secondaryIconParams);
}
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index cb714b2..b40493a 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -113,6 +113,14 @@
* the bounds were originally in
*/
public final boolean appsStackedVertically;
+ /**
+ * If {@code true}, that means at the time of creation of this object, the phone was in
+ * seascape orientation. This is important on devices with insets, because they do not split
+ * evenly -- one of the insets must be slightly larger to account for the inset.
+ * From landscape, it is the leftTop task that expands slightly.
+ * From seascape, it is the rightBottom task that expands slightly.
+ */
+ public final boolean initiatedFromSeascape;
public final int leftTopTaskId;
public final int rightBottomTaskId;
@@ -128,11 +136,22 @@
this.visualDividerBounds = new Rect(leftTopBounds.left, leftTopBounds.bottom,
leftTopBounds.right, rightBottomBounds.top);
appsStackedVertically = true;
+ initiatedFromSeascape = false;
} else {
// horizontal apps, vertical divider
this.visualDividerBounds = new Rect(leftTopBounds.right, leftTopBounds.top,
rightBottomBounds.left, leftTopBounds.bottom);
appsStackedVertically = false;
+ // The following check is unreliable on devices without insets
+ // (initiatedFromSeascape will always be set to false.) This happens to be OK for
+ // all our current uses, but should be refactored.
+ // TODO: Create a more reliable check, or refactor how splitting works on devices
+ // with insets.
+ if (rightBottomBounds.width() > leftTopBounds.width()) {
+ initiatedFromSeascape = true;
+ } else {
+ initiatedFromSeascape = false;
+ }
}
leftTaskPercent = this.leftTopBounds.width() / (float) rightBottomBounds.right;