Snap for 9762093 from 2065586a5d to udc-release
Change-Id: I7526f40d38e29c46baeb594d2dba480516672394
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
|
||||
@@ -755,7 +755,6 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
mBackButton.setImageDrawable(rotateDrawable);
|
||||
mBackButton.setScaleType(ImageView.ScaleType.FIT_CENTER);
|
||||
mBackButton.setPadding(paddingleft, paddingTop, paddingRight, paddingBottom);
|
||||
mBackButton.setScaleX(Utilities.isRtl(mContext.getResources()) ? -1f : 1f);
|
||||
|
||||
mHomeButton.setImageDrawable(
|
||||
mHomeButton.getContext().getDrawable(R.drawable.ic_sysbar_home_kids));
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
|
||||
import com.android.launcher3.taskbar.overlay.TaskbarOverlayContext;
|
||||
@@ -61,13 +60,6 @@ public class TaskbarAllAppsContainerView extends
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateBackground(DeviceProfile deviceProfile) {
|
||||
super.updateBackground(deviceProfile);
|
||||
// TODO(b/240670050): Remove this and add header protection for the taskbar entrypoint.
|
||||
mBottomSheetBackground.setBackgroundResource(R.drawable.bg_rounded_corner_bottom_sheet);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInAllApps() {
|
||||
// All apps is always open
|
||||
|
||||
+14
-26
@@ -23,8 +23,6 @@ import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.window.BackEvent;
|
||||
import android.window.OnBackAnimationCallback;
|
||||
import android.window.OnBackInvokedDispatcher;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
@@ -57,28 +55,6 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverla
|
||||
mAllAppsCallbacks = callbacks;
|
||||
}
|
||||
|
||||
private final OnBackAnimationCallback mOnBackAnimationCallback = new OnBackAnimationCallback() {
|
||||
@Override
|
||||
public void onBackCancelled() {
|
||||
TaskbarAllAppsSlideInView.this.onBackCancelled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
TaskbarAllAppsSlideInView.this.onBackInvoked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackProgressed(BackEvent backEvent) {
|
||||
TaskbarAllAppsSlideInView.this.onBackProgressed(backEvent.getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackStarted(BackEvent backEvent) {
|
||||
TaskbarAllAppsSlideInView.this.onBackStarted();
|
||||
}
|
||||
};
|
||||
|
||||
/** Opens the all apps view. */
|
||||
void show(boolean animate) {
|
||||
if (mIsOpen || mOpenCloseAnimator.isRunning()) {
|
||||
@@ -97,8 +73,10 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverla
|
||||
}
|
||||
|
||||
if (FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get()) {
|
||||
mAppsView.getAppsRecyclerViewContainer().setOutlineProvider(mViewOutlineProvider);
|
||||
mAppsView.getAppsRecyclerViewContainer().setClipToOutline(true);
|
||||
findOnBackInvokedDispatcher().registerOnBackInvokedCallback(
|
||||
OnBackInvokedDispatcher.PRIORITY_DEFAULT, mOnBackAnimationCallback);
|
||||
OnBackInvokedDispatcher.PRIORITY_DEFAULT, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,7 +89,7 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverla
|
||||
protected void handleClose(boolean animate) {
|
||||
handleClose(animate, mAllAppsCallbacks.getCloseDuration());
|
||||
if (FeatureFlags.ENABLE_BACK_SWIPE_LAUNCHER_ANIMATION.get()) {
|
||||
findOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(mOnBackAnimationCallback);
|
||||
findOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,6 +113,16 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarOverla
|
||||
setShiftRange(dp.allAppsShiftRange);
|
||||
|
||||
mActivityContext.addOnDeviceProfileChangeListener(this);
|
||||
setContentBackgroundWithParent(
|
||||
getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet),
|
||||
mAppsView.getBottomSheetBackground());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onScaleProgressChanged() {
|
||||
super.onScaleProgressChanged();
|
||||
mAppsView.setClipChildren(!mIsBackProgressing);
|
||||
mAppsView.getAppsRecyclerViewContainer().setClipChildren(!mIsBackProgressing);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -97,7 +97,6 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.OnBackPressedHandler;
|
||||
import com.android.launcher3.QuickstepAccessibilityDelegate;
|
||||
import com.android.launcher3.QuickstepTransitionManager;
|
||||
import com.android.launcher3.R;
|
||||
@@ -172,7 +171,6 @@ import com.android.quickstep.views.FloatingTaskView;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.unfold.RemoteUnfoldSharedComponent;
|
||||
import com.android.systemui.unfold.UnfoldSharedComponent;
|
||||
@@ -192,7 +190,6 @@ import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -745,48 +742,50 @@ public class QuickstepLauncher extends Launcher {
|
||||
OnBackInvokedDispatcher.PRIORITY_DEFAULT,
|
||||
new OnBackAnimationCallback() {
|
||||
|
||||
@Nullable OnBackPressedHandler mActiveOnBackPressedHandler;
|
||||
@Nullable OnBackAnimationCallback mActiveOnBackAnimationCallback;
|
||||
|
||||
@Override
|
||||
public void onBackStarted(@NonNull BackEvent backEvent) {
|
||||
if (mActiveOnBackPressedHandler != null) {
|
||||
mActiveOnBackPressedHandler.onBackCancelled();
|
||||
if (mActiveOnBackAnimationCallback != null) {
|
||||
mActiveOnBackAnimationCallback.onBackCancelled();
|
||||
}
|
||||
mActiveOnBackPressedHandler = getOnBackPressedHandler();
|
||||
mActiveOnBackPressedHandler.onBackStarted();
|
||||
mActiveOnBackAnimationCallback = getOnBackAnimationCallback();
|
||||
mActiveOnBackAnimationCallback.onBackStarted(backEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
// Recreate mActiveOnBackPressedHandler if necessary to avoid NPE because:
|
||||
// Recreate mActiveOnBackAnimationCallback if necessary to avoid NPE
|
||||
// because:
|
||||
// 1. b/260636433: In 3-button-navigation mode, onBackStarted() is not
|
||||
// called on ACTION_DOWN before onBackInvoked() is called in ACTION_UP.
|
||||
// 2. Launcher#onBackPressed() will call onBackInvoked() without calling
|
||||
// onBackInvoked() beforehand.
|
||||
if (mActiveOnBackPressedHandler == null) {
|
||||
mActiveOnBackPressedHandler = getOnBackPressedHandler();
|
||||
if (mActiveOnBackAnimationCallback == null) {
|
||||
mActiveOnBackAnimationCallback = getOnBackAnimationCallback();
|
||||
}
|
||||
mActiveOnBackPressedHandler.onBackInvoked();
|
||||
mActiveOnBackPressedHandler = null;
|
||||
mActiveOnBackAnimationCallback.onBackInvoked();
|
||||
mActiveOnBackAnimationCallback = null;
|
||||
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onBackInvoked");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackProgressed(@NonNull BackEvent backEvent) {
|
||||
if (!FeatureFlags.IS_STUDIO_BUILD && mActiveOnBackPressedHandler == null) {
|
||||
if (!FeatureFlags.IS_STUDIO_BUILD
|
||||
&& mActiveOnBackAnimationCallback == null) {
|
||||
return;
|
||||
}
|
||||
mActiveOnBackPressedHandler
|
||||
.onBackProgressed(backEvent.getProgress());
|
||||
mActiveOnBackAnimationCallback.onBackProgressed(backEvent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackCancelled() {
|
||||
if (!FeatureFlags.IS_STUDIO_BUILD && mActiveOnBackPressedHandler == null) {
|
||||
if (!FeatureFlags.IS_STUDIO_BUILD
|
||||
&& mActiveOnBackAnimationCallback == null) {
|
||||
return;
|
||||
}
|
||||
mActiveOnBackPressedHandler.onBackCancelled();
|
||||
mActiveOnBackPressedHandler = null;
|
||||
mActiveOnBackAnimationCallback.onBackCancelled();
|
||||
mActiveOnBackAnimationCallback = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class PluginManagerWrapper {
|
||||
List<String> privilegedPlugins = Collections.emptyList();
|
||||
PluginInstance.Factory instanceFactory = new PluginInstance.Factory(
|
||||
getClass().getClassLoader(), new PluginInstance.InstanceFactory<>(),
|
||||
new PluginInstance.VersionChecker(), privilegedPlugins,
|
||||
new PluginInstance.VersionCheckerImpl(), privilegedPlugins,
|
||||
Utilities.IS_DEBUG_DEVICE);
|
||||
PluginActionManager.Factory instanceManagerFactory = new PluginActionManager.Factory(
|
||||
c, c.getPackageManager(), c.getMainExecutor(), MODEL_EXECUTOR,
|
||||
|
||||
@@ -547,8 +547,8 @@ public class TouchInteractionService extends Service
|
||||
boolean isFreeformActive =
|
||||
(systemUiStateFlags & SYSUI_STATE_FREEFORM_ACTIVE_IN_DESKTOP_MODE) != 0;
|
||||
if (wasFreeformActive != isFreeformActive) {
|
||||
DesktopVisibilityController controller = mOverviewComponentObserver
|
||||
.getActivityInterface().getDesktopVisibilityController();
|
||||
DesktopVisibilityController controller =
|
||||
LauncherActivityInterface.INSTANCE.getDesktopVisibilityController();
|
||||
if (controller != null) {
|
||||
controller.setFreeformTasksVisible(isFreeformActive);
|
||||
}
|
||||
|
||||
@@ -147,6 +147,8 @@ import com.android.launcher3.logging.StatsLogManager;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.statemanager.BaseState;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.testing.TestLogging;
|
||||
import com.android.launcher3.testing.shared.TestProtocol;
|
||||
import com.android.launcher3.touch.OverScroll;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.util.DynamicResource;
|
||||
@@ -4497,6 +4499,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
* Attempts to initiate split with an existing taskView, if one exists
|
||||
*/
|
||||
public void initiateSplitSelect(SplitSelectSource splitSelectSource) {
|
||||
TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "enterSplitSelect");
|
||||
mSplitSelectSource = splitSelectSource;
|
||||
mSplitHiddenTaskView = getTaskViewByTaskId(splitSelectSource.alreadyRunningTaskId);
|
||||
mSplitHiddenTaskViewIndex = indexOfChild(mSplitHiddenTaskView);
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.quickstep;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
import com.android.launcher3.ui.TaplTestsLauncher3;
|
||||
import com.android.launcher3.util.rule.TestStabilityRule;
|
||||
import com.android.quickstep.TaskbarModeSwitchRule.TaskbarModeSwitch;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TaplTestsSplitscreen extends AbstractQuickStepTest {
|
||||
private static final String CALCULATOR_APP_NAME = "Calculator";
|
||||
private static final String CALCULATOR_APP_PACKAGE =
|
||||
resolveSystemApp(Intent.CATEGORY_APP_CALCULATOR);
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
TaplTestsLauncher3.initialize(this);
|
||||
|
||||
mLauncher.getWorkspace()
|
||||
.deleteAppIcon(mLauncher.getWorkspace().getHotseatAppIcon(0))
|
||||
.switchToAllApps()
|
||||
.getAppIcon(CALCULATOR_APP_NAME)
|
||||
.dragToHotseat(0);
|
||||
|
||||
startAppFast(CALCULATOR_APP_PACKAGE);
|
||||
if (mLauncher.isTablet()) {
|
||||
mLauncher.enableBlockTimeout(true);
|
||||
mLauncher.showTaskbarIfHidden();
|
||||
}
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (mLauncher.isTablet()) {
|
||||
mLauncher.enableBlockTimeout(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
// TODO (b/270201357): When this test is proven stable, remove this TestStabilityRule and
|
||||
// introduce into presubmit as well.
|
||||
@TestStabilityRule.Stability(
|
||||
flavors = TestStabilityRule.LOCAL | TestStabilityRule.PLATFORM_POSTSUBMIT)
|
||||
@PortraitLandscape
|
||||
@TaskbarModeSwitch
|
||||
public void testSplitAppFromHomeWithItself() throws Exception {
|
||||
Assume.assumeTrue(mLauncher.isTablet());
|
||||
|
||||
mLauncher.goHome()
|
||||
.switchToAllApps()
|
||||
.getAppIcon(CALCULATOR_APP_NAME)
|
||||
.openMenu()
|
||||
.getSplitScreenMenuItem()
|
||||
.click();
|
||||
|
||||
mLauncher.getLaunchedAppState()
|
||||
.getTaskbar()
|
||||
.getAppIcon(CALCULATOR_APP_NAME)
|
||||
.launchIntoSplitScreen();
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
<com.android.launcher3.notification.NotificationMainView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="@dimen/notification_container_height"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- header -->
|
||||
@@ -25,14 +25,14 @@
|
||||
android:id="@+id/header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingEnd="@dimen/notification_padding"
|
||||
android:paddingStart="@dimen/notification_padding">
|
||||
android:paddingEnd="@dimen/notification_padding_end"
|
||||
android:paddingTop="@dimen/notification_padding_header_top"
|
||||
android:paddingStart="@dimen/notification_header_padding_start">
|
||||
<TextView
|
||||
android:id="@+id/notification_text"
|
||||
android:paddingTop="@dimen/notification_padding"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|start"
|
||||
android:layout_gravity="top|start"
|
||||
android:text="@string/notifications_header"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/notification_header_text_size"
|
||||
@@ -42,7 +42,7 @@
|
||||
android:layout_width="@dimen/notification_circle_icon_size"
|
||||
android:layout_height="@dimen/notification_circle_icon_size"
|
||||
android:background="@drawable/notification_circle"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_gravity="top|end"
|
||||
android:gravity="center"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/notification_header_count_text_size"
|
||||
@@ -54,6 +54,8 @@
|
||||
android:id="@+id/main_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingTop="@dimen/notification_padding_top"
|
||||
android:paddingBottom="@dimen/notification_padding_bottom"
|
||||
android:focusable="true" >
|
||||
|
||||
<LinearLayout
|
||||
@@ -62,9 +64,7 @@
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="@dimen/notification_padding"
|
||||
android:paddingBottom="@dimen/notification_padding"
|
||||
android:paddingEnd="@dimen/notification_padding"
|
||||
android:paddingEnd="@dimen/notification_padding_end"
|
||||
android:paddingStart="@dimen/notification_main_text_padding_start">
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
@@ -91,9 +91,8 @@
|
||||
android:id="@+id/popup_item_icon"
|
||||
android:layout_width="@dimen/notification_icon_size"
|
||||
android:layout_height="@dimen/notification_icon_size"
|
||||
android:layout_gravity="start"
|
||||
android:layout_marginTop="@dimen/notification_padding"
|
||||
android:layout_marginStart="@dimen/notification_icon_padding" />
|
||||
android:layout_gravity="start|center_vertical"
|
||||
android:layout_marginStart="@dimen/notification_icon_padding_start"/>
|
||||
|
||||
</FrameLayout>
|
||||
</com.android.launcher3.notification.NotificationMainView>
|
||||
@@ -18,8 +18,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/system_shortcut_header_icon_touch_size"
|
||||
android:layout_height="@dimen/system_shortcut_header_icon_touch_size"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:tint="?attr/iconOnlyShortcutColor"
|
||||
android:tintMode="src_in"
|
||||
android:padding="@dimen/system_shortcut_header_icon_padding"
|
||||
android:theme="@style/PopupItem" />
|
||||
android:theme="@style/PopupItemIconOnly" />
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2023 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.
|
||||
-->
|
||||
|
||||
<ImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/system_shortcut_header_icon_touch_size"
|
||||
android:layout_height="@dimen/system_shortcut_header_icon_touch_size"
|
||||
android:tint="?attr/iconOnlyShortcutColor"
|
||||
android:tintMode="src_in"
|
||||
android:padding="@dimen/system_shortcut_header_icon_padding"
|
||||
android:paddingStart="@dimen/system_shortcut_header_icon_padding_inner"
|
||||
android:paddingEnd="@dimen/system_shortcut_header_icon_padding_outer"
|
||||
android:theme="@style/PopupItemIconOnly" />
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2023 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.
|
||||
-->
|
||||
|
||||
<ImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="@dimen/system_shortcut_header_icon_touch_size"
|
||||
android:layout_height="@dimen/system_shortcut_header_icon_touch_size"
|
||||
android:tint="?attr/iconOnlyShortcutColor"
|
||||
android:tintMode="src_in"
|
||||
android:padding="@dimen/system_shortcut_header_icon_padding"
|
||||
android:paddingStart="@dimen/system_shortcut_header_icon_padding_outer"
|
||||
android:paddingEnd="@dimen/system_shortcut_header_icon_padding_inner"
|
||||
android:theme="@style/PopupItemIconOnly" />
|
||||
+19
-11
@@ -281,7 +281,7 @@
|
||||
<dimen name="deep_shortcuts_elevation">2dp</dimen>
|
||||
<dimen name="bg_popup_padding">2dp</dimen>
|
||||
<dimen name="bg_popup_item_width">216dp</dimen>
|
||||
<dimen name="bg_popup_item_height">56dp</dimen>
|
||||
<dimen name="bg_popup_item_height">52dp</dimen>
|
||||
<dimen name="bg_popup_item_vertical_padding">12dp</dimen>
|
||||
<dimen name="pre_drag_view_scale">6dp</dimen>
|
||||
<!-- an icon with shortcuts must be dragged this far before the container is removed. -->
|
||||
@@ -290,10 +290,10 @@
|
||||
<dimen name="popup_margin">2dp</dimen>
|
||||
<dimen name="popup_single_item_radius">100dp</dimen>
|
||||
<dimen name="popup_smaller_radius">4dp</dimen>
|
||||
<dimen name="deep_shortcut_drawable_padding">12dp</dimen>
|
||||
<dimen name="deep_shortcut_drawable_padding">16dp</dimen>
|
||||
<dimen name="deep_shortcut_drag_handle_size">16dp</dimen>
|
||||
<dimen name="popup_padding_start">10dp</dimen>
|
||||
<dimen name="popup_padding_end">16dp</dimen>
|
||||
<dimen name="popup_padding_end">14dp</dimen>
|
||||
<dimen name="popup_vertical_padding">4dp</dimen>
|
||||
<dimen name="popup_arrow_width">12dp</dimen>
|
||||
<dimen name="popup_arrow_height">10dp</dimen>
|
||||
@@ -301,32 +301,40 @@
|
||||
<!-- popup_padding_start + deep_shortcut_icon_size / 2 -->
|
||||
<dimen name="popup_arrow_horizontal_center_offset">26dp</dimen>
|
||||
<dimen name="popup_arrow_corner_radius">2dp</dimen>
|
||||
<!-- popup_padding_start + deep_shortcut_icon_size + 10dp -->
|
||||
<dimen name="deep_shortcuts_text_padding_start">52dp</dimen>
|
||||
<!-- popup_padding_start + deep_shortcut_icon_size + 12dp -->
|
||||
<dimen name="deep_shortcuts_text_padding_start">54dp</dimen>
|
||||
<dimen name="system_shortcut_icon_size">20dp</dimen>
|
||||
<!-- popup_arrow_horizontal_center_offset - system_shortcut_icon_size / 2 -->
|
||||
<dimen name="system_shortcut_margin_start">16dp</dimen>
|
||||
<dimen name="system_shortcut_header_height">56dp</dimen>
|
||||
<dimen name="system_shortcut_header_height">52dp</dimen>
|
||||
<dimen name="system_shortcut_header_icon_touch_size">48dp</dimen>
|
||||
<!-- (system_shortcut_header_icon_touch_size - system_shortcut_icon_size) / 2 -->
|
||||
<dimen name="system_shortcut_header_icon_padding">14dp</dimen>
|
||||
<!-- side of start/end icon near to container edge -->
|
||||
<dimen name="system_shortcut_header_icon_padding_outer">16dp</dimen>
|
||||
<!-- side of start/end icon far from container edge -->
|
||||
<dimen name="system_shortcut_header_icon_padding_inner">12dp</dimen>
|
||||
|
||||
|
||||
<!-- Notifications -->
|
||||
<dimen name="bg_round_rect_radius">8dp</dimen>
|
||||
<dimen name="notification_container_height">104dp</dimen>
|
||||
<dimen name="notification_max_trans">8dp</dimen>
|
||||
<dimen name="notification_space">8dp</dimen>
|
||||
<dimen name="notification_padding">16dp</dimen>
|
||||
<dimen name="notification_padding_top">18dp</dimen>
|
||||
<dimen name="notification_padding_end">16dp</dimen>
|
||||
<dimen name="notification_padding_bottom">12dp</dimen>
|
||||
<dimen name="notification_padding_top">12dp</dimen>
|
||||
<dimen name="notification_padding_header_top">16dp</dimen>
|
||||
<dimen name="notification_header_padding_start">14dp</dimen>
|
||||
<dimen name="notification_header_text_size">14sp</dimen>
|
||||
<dimen name="notification_header_count_text_size">12sp</dimen>
|
||||
<dimen name="notification_main_title_size">14sp</dimen>
|
||||
<dimen name="notification_main_text_size">14sp</dimen>
|
||||
<dimen name="notification_circle_icon_size">24dp</dimen>
|
||||
<dimen name="notification_icon_size">32dp</dimen>
|
||||
<!-- Space between edge and icon and icon and text -->
|
||||
<dimen name="notification_icon_padding">12dp</dimen>
|
||||
<dimen name="notification_icon_padding_start">10dp</dimen>
|
||||
<!-- notification_icon_padding + notification_icon_size + notification_icon_padding -->
|
||||
<dimen name="notification_main_text_padding_start">56dp</dimen>
|
||||
<dimen name="notification_main_text_padding_start">54dp</dimen>
|
||||
<dimen name="horizontal_ellipsis_size">18dp</dimen>
|
||||
|
||||
<!-- Overview -->
|
||||
|
||||
@@ -249,6 +249,11 @@
|
||||
<item name="android:colorControlHighlight">?attr/popupColorTertiary</item>
|
||||
</style>
|
||||
|
||||
<style name="PopupItemIconOnly">
|
||||
<item name="android:colorControlHighlight">?attr/popupColorTertiary</item>
|
||||
<item name="android:background">?android:attr/selectableItemBackgroundBorderless</item>
|
||||
</style>
|
||||
|
||||
<!-- Drop targets -->
|
||||
<style name="DropTargetButtonBase" parent="@android:style/TextAppearance.DeviceDefault.Medium">
|
||||
<item name="android:drawablePadding">@dimen/drop_target_button_drawable_padding</item>
|
||||
|
||||
@@ -24,7 +24,9 @@ import static com.android.launcher3.compat.AccessibilityManagerCompat.isAccessib
|
||||
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Pair;
|
||||
import android.view.MotionEvent;
|
||||
@@ -32,6 +34,7 @@ import android.view.View;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.widget.LinearLayout;
|
||||
import android.window.OnBackAnimationCallback;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
|
||||
@@ -46,8 +49,9 @@ import java.lang.annotation.RetentionPolicy;
|
||||
/**
|
||||
* Base class for a View which shows a floating UI on top of the launcher UI.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
public abstract class AbstractFloatingView extends LinearLayout implements TouchController,
|
||||
OnBackPressedHandler {
|
||||
OnBackAnimationCallback {
|
||||
|
||||
@IntDef(flag = true, value = {
|
||||
TYPE_FOLDER,
|
||||
|
||||
@@ -57,6 +57,8 @@ public abstract class ButtonDropTarget extends TextView
|
||||
public static final int TOOLTIP_LEFT = 1;
|
||||
public static final int TOOLTIP_RIGHT = 2;
|
||||
|
||||
private final Rect mTempRect = new Rect();
|
||||
|
||||
protected final Launcher mLauncher;
|
||||
|
||||
protected DropTargetBar mDropTargetBar;
|
||||
@@ -402,6 +404,21 @@ public abstract class ButtonDropTarget extends TextView
|
||||
secondLine));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the text will be clipped vertically within the provided availableHeight.
|
||||
*/
|
||||
private boolean isTextClippedVertically(int availableHeight) {
|
||||
availableHeight -= getPaddingTop() + getPaddingBottom();
|
||||
if (availableHeight <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
getPaint().getTextBounds(mText.toString(), 0, mText.length(), mTempRect);
|
||||
// Add bounds bottom to height, as text bounds height measures from the text baseline and
|
||||
// above, which characters can descend below
|
||||
return mTempRect.bottom + mTempRect.height() <= availableHeight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reduce the size of the text until it fits the measured width or reaches a minimum.
|
||||
*
|
||||
@@ -423,7 +440,9 @@ public abstract class ButtonDropTarget extends TextView
|
||||
float textSize = Utilities.pxToSp(getTextSize());
|
||||
|
||||
int availableWidth = getMeasuredWidth();
|
||||
while (isTextTruncated(availableWidth)) {
|
||||
int availableHeight = getMeasuredHeight();
|
||||
|
||||
while (isTextTruncated(availableWidth) || isTextClippedVertically(availableHeight)) {
|
||||
textSize -= step;
|
||||
if (textSize < minSize) {
|
||||
textSize = minSize;
|
||||
|
||||
@@ -116,9 +116,10 @@ import android.view.WindowManager.LayoutParams;
|
||||
import android.view.accessibility.AccessibilityEvent;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
import android.widget.Toast;
|
||||
import android.window.BackEvent;
|
||||
import android.window.OnBackAnimationCallback;
|
||||
|
||||
import androidx.annotation.CallSuper;
|
||||
import androidx.annotation.FloatRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
@@ -560,7 +561,7 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide {@link OnBackPressedHandler} in below order:
|
||||
* Provide {@link OnBackAnimationCallback} in below order:
|
||||
* <ol>
|
||||
* <li> auto cancel action mode handler
|
||||
* <li> drag handler
|
||||
@@ -575,7 +576,8 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
* Note that state handler will always be handling the back press event if the previous 3 don't.
|
||||
*/
|
||||
@NonNull
|
||||
protected OnBackPressedHandler getOnBackPressedHandler() {
|
||||
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
protected OnBackAnimationCallback getOnBackAnimationCallback() {
|
||||
// #1 auto cancel action mode handler
|
||||
if (isInAutoCancelActionMode()) {
|
||||
return this::finishAutoCancelActionMode;
|
||||
@@ -594,17 +596,16 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
}
|
||||
|
||||
// #4 state handler
|
||||
return new OnBackPressedHandler() {
|
||||
return new OnBackAnimationCallback() {
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
onStateBack();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackProgressed(
|
||||
@FloatRange(from = 0.0, to = 1.0) float backProgress) {
|
||||
public void onBackProgressed(@NonNull BackEvent backEvent) {
|
||||
mStateManager.getState().onBackProgressed(
|
||||
Launcher.this, backProgress);
|
||||
Launcher.this, backEvent.getProgress());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2117,8 +2118,9 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
}
|
||||
|
||||
@Override
|
||||
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
public void onBackPressed() {
|
||||
getOnBackPressedHandler().onBackInvoked();
|
||||
getOnBackAnimationCallback().onBackInvoked();
|
||||
}
|
||||
|
||||
protected void onStateBack() {
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
|
||||
/**
|
||||
* Interface that mimics {@link android.window.OnBackInvokedCallback} without dependencies on U's
|
||||
* API such as {@link android.window.BackEvent}.
|
||||
*
|
||||
* <p> Impl can assume below order during a back gesture:
|
||||
* <ol>
|
||||
* <li> [optional] one {@link #onBackStarted()} will be called to start the gesture
|
||||
* <li> zero or multiple {@link #onBackProgressed(float)} will be called during swipe gesture
|
||||
* <li> either one of {@link #onBackInvoked()} or {@link #onBackCancelled()} will be called to end
|
||||
* the gesture
|
||||
*/
|
||||
public interface OnBackPressedHandler {
|
||||
|
||||
/** Called when back has started. */
|
||||
default void onBackStarted() {}
|
||||
|
||||
/** Called when back is committed. */
|
||||
void onBackInvoked();
|
||||
|
||||
/** Called with back gesture's progress. */
|
||||
default void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float backProgress) {}
|
||||
|
||||
/** Called when user drops the back gesture. */
|
||||
default void onBackCancelled() {}
|
||||
}
|
||||
@@ -47,6 +47,7 @@ import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.view.WindowInsets;
|
||||
import android.widget.Button;
|
||||
@@ -266,6 +267,10 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
return mSearchUiManager;
|
||||
}
|
||||
|
||||
public View getBottomSheetBackground() {
|
||||
return mBottomSheetBackground;
|
||||
}
|
||||
|
||||
public View getSearchView() {
|
||||
return mSearchContainer;
|
||||
}
|
||||
@@ -905,7 +910,7 @@ public class ActivityAllAppsContainerView<T extends Context & ActivityContext>
|
||||
* The container for A-Z apps (the ViewPager for main+work tabs, or main RV). This is currently
|
||||
* hidden while searching.
|
||||
**/
|
||||
protected View getAppsRecyclerViewContainer() {
|
||||
public ViewGroup getAppsRecyclerViewContainer() {
|
||||
return mViewPager != null ? mViewPager : findViewById(R.id.apps_list_view);
|
||||
}
|
||||
|
||||
|
||||
@@ -264,14 +264,7 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
shortcuts.get(0), false);
|
||||
return;
|
||||
}
|
||||
mSystemShortcutContainer = inflateAndAdd(R.layout.system_shortcut_icons_container, this, 0);
|
||||
for (int i = 0; i < shortcuts.size(); i++) {
|
||||
initializeSystemShortcut(
|
||||
R.layout.system_shortcut_icon_only,
|
||||
mSystemShortcutContainer,
|
||||
shortcuts.get(i),
|
||||
i < shortcuts.size() - 1);
|
||||
}
|
||||
addSystemShortcutsIconsOnly(shortcuts);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
@@ -404,9 +397,7 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
List<SystemShortcut> nonWidgetSystemShortcuts =
|
||||
getNonWidgetSystemShortcuts(systemShortcuts);
|
||||
// If total shortcuts over threshold, collapse system shortcuts to single row
|
||||
addSystemShortcutsMaterialU(nonWidgetSystemShortcuts,
|
||||
R.layout.system_shortcut_icons_container_material_u,
|
||||
R.layout.system_shortcut_icon_only);
|
||||
addSystemShortcutsIconsOnly(nonWidgetSystemShortcuts);
|
||||
// May need to recalculate row width
|
||||
mContainerWidth = Math.max(mContainerWidth,
|
||||
nonWidgetSystemShortcuts.size() * getResources()
|
||||
@@ -473,6 +464,33 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
}
|
||||
}
|
||||
|
||||
private void addSystemShortcutsIconsOnly(List<SystemShortcut> systemShortcuts) {
|
||||
if (systemShortcuts.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
mSystemShortcutContainer = ENABLE_MATERIAL_U_POPUP.get()
|
||||
? inflateAndAdd(R.layout.system_shortcut_icons_container_material_u, this)
|
||||
: inflateAndAdd(R.layout.system_shortcut_icons_container, this, 0);
|
||||
|
||||
for (int i = 0; i < systemShortcuts.size(); i++) {
|
||||
@LayoutRes int shortcutIconLayout = R.layout.system_shortcut_icon_only;
|
||||
boolean shouldAppendSpacer = true;
|
||||
|
||||
if (i == 0) {
|
||||
shortcutIconLayout = R.layout.system_shortcut_icon_only_start;
|
||||
} else if (i == systemShortcuts.size() - 1) {
|
||||
shortcutIconLayout = R.layout.system_shortcut_icon_only_end;
|
||||
shouldAppendSpacer = false;
|
||||
}
|
||||
initializeSystemShortcut(
|
||||
shortcutIconLayout,
|
||||
mSystemShortcutContainer,
|
||||
systemShortcuts.get(i),
|
||||
shouldAppendSpacer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inflates and adds [deepShortcutCount] number of DeepShortcutView for the to a new container
|
||||
* @param deepShortcutCount number of DeepShortcutView instances to add
|
||||
@@ -552,13 +570,13 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
* @param resId Resource id to use for SystemShortcut View.
|
||||
* @param container ViewGroup to add the shortcut View to as a parent
|
||||
* @param info The SystemShortcut instance to create a View for.
|
||||
* @param shouldAddSpacer If True, will add a spacer after the shortcut, when showing the
|
||||
* @param shouldAppendSpacer If True, will add a spacer after the shortcut, when showing the
|
||||
* SystemShortcut as an icon only. Used to space the shortcut icons
|
||||
* evenly.
|
||||
* @return The view inflated for the SystemShortcut
|
||||
*/
|
||||
protected View initializeSystemShortcut(int resId, ViewGroup container, SystemShortcut info,
|
||||
boolean shouldAddSpacer) {
|
||||
boolean shouldAppendSpacer) {
|
||||
View view = inflateAndAdd(resId, container);
|
||||
if (view instanceof DeepShortcutView) {
|
||||
// System shortcut takes entire row with icon and text
|
||||
@@ -567,7 +585,7 @@ public class PopupContainerWithArrow<T extends Context & ActivityContext>
|
||||
} else if (view instanceof ImageView) {
|
||||
// System shortcut is just an icon
|
||||
info.setIconAndContentDescriptionFor((ImageView) view);
|
||||
if (shouldAddSpacer) inflateAndAdd(R.layout.system_shortcut_spacer, container);
|
||||
if (shouldAppendSpacer) inflateAndAdd(R.layout.system_shortcut_spacer, container);
|
||||
view.setTooltipText(view.getContentDescription());
|
||||
}
|
||||
view.setTag(info);
|
||||
|
||||
@@ -33,7 +33,7 @@ import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||
public class ScrollableLayoutManager extends GridLayoutManager {
|
||||
|
||||
public static final float PREDICTIVE_BACK_MIN_SCALE = 0.9f;
|
||||
private static final float EXTRA_BOTTOM_SPACE_BY_HEIGHT_PERCENT =
|
||||
public static final float EXTRA_BOTTOM_SPACE_BY_HEIGHT_PERCENT =
|
||||
(1 - PREDICTIVE_BACK_MIN_SCALE) / 2;
|
||||
|
||||
// keyed on item type
|
||||
|
||||
@@ -28,17 +28,22 @@ import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Property;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.view.animation.Interpolator;
|
||||
import android.window.BackEvent;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Px;
|
||||
|
||||
@@ -96,8 +101,21 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
|
||||
|
||||
private final AnimatedFloat mSlideInViewScale =
|
||||
new AnimatedFloat(this::onScaleProgressChanged, VIEW_NO_SCALE);
|
||||
private boolean mIsBackProgressing;
|
||||
protected boolean mIsBackProgressing;
|
||||
@Nullable private Drawable mContentBackground;
|
||||
@Nullable private View mContentBackgroundParentView;
|
||||
|
||||
protected final ViewOutlineProvider mViewOutlineProvider = new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
outline.setRect(
|
||||
0,
|
||||
0,
|
||||
view.getMeasuredWidth(),
|
||||
view.getMeasuredHeight() + getBottomOffsetPx()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
public AbstractSlideInView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
@@ -119,10 +137,6 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
|
||||
mColorScrim = scrimColor != -1 ? createColorScrim(context, scrimColor) : null;
|
||||
}
|
||||
|
||||
protected void setContentBackground(Drawable drawable) {
|
||||
mContentBackground = drawable;
|
||||
}
|
||||
|
||||
protected void attachToContainer() {
|
||||
if (mColorScrim != null) {
|
||||
getPopupContainer().addView(mColorScrim);
|
||||
@@ -181,8 +195,9 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float progress) {
|
||||
super.onBackProgressed(progress);
|
||||
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
public void onBackProgressed(BackEvent backEvent) {
|
||||
final float progress = backEvent.getProgress();
|
||||
float deceleratedProgress =
|
||||
Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(progress);
|
||||
mIsBackProgressing = progress > 0f;
|
||||
@@ -190,7 +205,7 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
|
||||
+ (1 - PREDICTIVE_BACK_MIN_SCALE) * (1 - deceleratedProgress));
|
||||
}
|
||||
|
||||
private void onScaleProgressChanged() {
|
||||
protected void onScaleProgressChanged() {
|
||||
float scaleProgress = mSlideInViewScale.value;
|
||||
SCALE_PROPERTY.set(this, scaleProgress);
|
||||
setClipChildren(!mIsBackProgressing);
|
||||
@@ -222,16 +237,27 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
|
||||
super.dispatchDraw(canvas);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set slide in view's background {@link Drawable} which will be draw onto a parent view in
|
||||
* {@link #dispatchDraw(Canvas)}
|
||||
*/
|
||||
protected void setContentBackgroundWithParent(
|
||||
@NonNull Drawable drawable, @NonNull View parentView) {
|
||||
mContentBackground = drawable;
|
||||
mContentBackgroundParentView = parentView;
|
||||
}
|
||||
|
||||
/** Draw scaled background during predictive back animation. */
|
||||
protected void drawScaledBackground(Canvas canvas) {
|
||||
if (mContentBackground == null) {
|
||||
private void drawScaledBackground(Canvas canvas) {
|
||||
if (mContentBackground == null || mContentBackgroundParentView == null) {
|
||||
return;
|
||||
}
|
||||
mContentBackground.setBounds(
|
||||
mContent.getLeft(),
|
||||
mContent.getTop() + (int) mContent.getTranslationY(),
|
||||
mContent.getRight(),
|
||||
mContent.getBottom() + (mIsBackProgressing ? getBottomOffsetPx() : 0));
|
||||
mContentBackgroundParentView.getLeft(),
|
||||
mContentBackgroundParentView.getTop() + (int) mContent.getTranslationY(),
|
||||
mContentBackgroundParentView.getRight(),
|
||||
mContentBackgroundParentView.getBottom()
|
||||
+ (mIsBackProgressing ? getBottomOffsetPx() : 0));
|
||||
mContentBackground.draw(canvas);
|
||||
}
|
||||
|
||||
|
||||
@@ -112,13 +112,14 @@ public class WidgetsBottomSheet extends BaseWidgetSheet {
|
||||
if (!hasSeenEducationTip()) {
|
||||
addOnLayoutChangeListener(mLayoutChangeListenerToShowTips);
|
||||
}
|
||||
setContentBackground(getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mContent = findViewById(R.id.widgets_bottom_sheet);
|
||||
setContentBackgroundWithParent(
|
||||
getContext().getDrawable(R.drawable.bg_rounded_corner_bottom_sheet), mContent);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,12 +25,13 @@ import static com.android.launcher3.testing.shared.TestProtocol.NORMAL_STATE_ORD
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.pm.LauncherApps;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Outline;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
@@ -41,7 +42,6 @@ import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewOutlineProvider;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.view.animation.Interpolator;
|
||||
@@ -49,8 +49,8 @@ import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.window.BackEvent;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Px;
|
||||
@@ -170,18 +170,6 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
}
|
||||
};
|
||||
|
||||
private final ViewOutlineProvider mViewOutlineProvider = new ViewOutlineProvider() {
|
||||
@Override
|
||||
public void getOutline(View view, Outline outline) {
|
||||
outline.setRect(
|
||||
0,
|
||||
0,
|
||||
view.getMeasuredWidth(),
|
||||
view.getMeasuredHeight() + getBottomOffsetPx()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@Px private final int mTabsHeight;
|
||||
|
||||
@Nullable private WidgetsRecyclerView mCurrentWidgetsRecyclerView;
|
||||
@@ -227,7 +215,6 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
|
||||
mUserManagerState.init(UserCache.INSTANCE.get(context),
|
||||
context.getSystemService(UserManager.class));
|
||||
setContentBackground(getContext().getDrawable(R.drawable.bg_widgets_full_sheet));
|
||||
}
|
||||
|
||||
public WidgetsFullSheet(Context context, AttributeSet attrs) {
|
||||
@@ -238,6 +225,8 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mContent = findViewById(R.id.container);
|
||||
setContentBackgroundWithParent(getContext().getDrawable(R.drawable.bg_widgets_full_sheet),
|
||||
mContent);
|
||||
|
||||
mContent.setOutlineProvider(mViewOutlineProvider);
|
||||
mContent.setClipToOutline(true);
|
||||
@@ -373,9 +362,10 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackProgressed(@FloatRange(from = 0.0, to = 1.0) float progress) {
|
||||
super.onBackProgressed(progress);
|
||||
mFastScroller.setVisibility(progress > 0 ? View.INVISIBLE : View.VISIBLE);
|
||||
@TargetApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
public void onBackProgressed(@NonNull BackEvent backEvent) {
|
||||
super.onBackProgressed(backEvent);
|
||||
mFastScroller.setVisibility(backEvent.getProgress() > 0 ? View.INVISIBLE : View.VISIBLE);
|
||||
}
|
||||
|
||||
private void attachScrollbarToRecyclerView(WidgetsRecyclerView recyclerView) {
|
||||
|
||||
@@ -54,5 +54,14 @@ public abstract class AppIconMenu {
|
||||
return createMenuItem(menuItem);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a menu item that matches the text "Split screen". Fails if it doesn't exist.
|
||||
*/
|
||||
public SplitScreenMenuItem getSplitScreenMenuItem() {
|
||||
final UiObject2 menuItem = mLauncher.waitForObjectInContainer(mDeepShortcutsContainer,
|
||||
AppIcon.getAppIconSelector("Split screen", mLauncher));
|
||||
return new SplitScreenMenuItem(mLauncher, menuItem);
|
||||
}
|
||||
|
||||
protected abstract AppIconMenuItem createMenuItem(UiObject2 menuItem);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,27 @@ public abstract class Launchable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clicks a launcher object to initiate splitscreen, where the selected app will be one of two
|
||||
* apps running on the screen. Should be called when Launcher is in a "split staging" state
|
||||
* and is waiting for the user's selection of a second app. Expects a SPLIT_START_EVENT to be
|
||||
* fired when the click is executed.
|
||||
*/
|
||||
public LaunchedAppState launchIntoSplitScreen() {
|
||||
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
|
||||
"want to launch split tasks from " + launchableType())) {
|
||||
LauncherInstrumentation.log("Launchable.launch before click "
|
||||
+ mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
|
||||
|
||||
mLauncher.clickLauncherObject(mObject);
|
||||
|
||||
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
|
||||
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, OverviewTask.SPLIT_START_EVENT);
|
||||
return new LaunchedAppState(mLauncher);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected LaunchedAppState assertAppLaunched(BySelector selector) {
|
||||
mLauncher.assertTrue(
|
||||
"App didn't start: (" + selector + ")",
|
||||
|
||||
@@ -37,10 +37,9 @@ import java.util.stream.Collectors;
|
||||
public final class OverviewTask {
|
||||
private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
|
||||
|
||||
static final Pattern TASK_START_EVENT =
|
||||
Pattern.compile("startActivityFromRecentsAsync");
|
||||
static final Pattern SPLIT_START_EVENT =
|
||||
Pattern.compile("launchSplitTasks");
|
||||
static final Pattern TASK_START_EVENT = Pattern.compile("startActivityFromRecentsAsync");
|
||||
static final Pattern SPLIT_SELECT_EVENT = Pattern.compile("enterSplitSelect");
|
||||
static final Pattern SPLIT_START_EVENT = Pattern.compile("launchSplitTasks");
|
||||
private final LauncherInstrumentation mLauncher;
|
||||
private final UiObject2 mTask;
|
||||
private final BaseOverview mOverview;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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.tapl;
|
||||
|
||||
import androidx.test.uiautomator.UiObject2;
|
||||
|
||||
import com.android.launcher3.testing.shared.TestProtocol;
|
||||
|
||||
/**
|
||||
* A class representing the "Split screen" menu item in the app long-press menu. Used for TAPL
|
||||
* testing in a similar way as other menu items {@link AppIconMenuItem}, but unlike AppIconMenuItem,
|
||||
* the split screen command does not trigger an app launch. Instead, it causes Launcher to shift to
|
||||
* a different state (OverviewSplitSelect).
|
||||
*/
|
||||
public final class SplitScreenMenuItem {
|
||||
private final LauncherInstrumentation mLauncher;
|
||||
private final UiObject2 mObject;
|
||||
|
||||
SplitScreenMenuItem(LauncherInstrumentation launcher, UiObject2 object) {
|
||||
mLauncher = launcher;
|
||||
mObject = object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a click command on this menu item. Expects a SPLIT_SELECT_EVENT to be fired.
|
||||
*/
|
||||
public void click() {
|
||||
try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
|
||||
"want to enter split select from app long-press menu")) {
|
||||
LauncherInstrumentation.log("clicking on split screen menu item "
|
||||
+ mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
|
||||
|
||||
mLauncher.clickLauncherObject(mObject);
|
||||
|
||||
try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
|
||||
mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, OverviewTask.SPLIT_SELECT_EVENT);
|
||||
mLauncher.waitForLauncherObject("split_placeholder");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user