Snap for 8535289 from 11339c644e to tm-qpr1-release
Change-Id: Iee40ceb087f2a3ee34e893c7c09876b78fde82f3
This commit is contained in:
@@ -24,6 +24,9 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
|
||||
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
|
||||
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
|
||||
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.ALL_APPS_PAGE_PROGRESS_INDEX;
|
||||
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.MINUS_ONE_PAGE_PROGRESS_INDEX;
|
||||
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.WIDGETS_PAGE_PROGRESS_INDEX;
|
||||
import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
|
||||
import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE;
|
||||
import static com.android.launcher3.util.DisplayController.NavigationMode.TWO_BUTTONS;
|
||||
@@ -229,6 +232,28 @@ public abstract class BaseQuickstepLauncher extends Launcher {
|
||||
public void onScrollChanged(float progress) {
|
||||
super.onScrollChanged(progress);
|
||||
mDepthController.onOverlayScrollChanged(progress);
|
||||
onTaskbarInAppDisplayProgressUpdate(progress, MINUS_ONE_PAGE_PROGRESS_INDEX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAllAppsTransition(float progress) {
|
||||
super.onAllAppsTransition(progress);
|
||||
onTaskbarInAppDisplayProgressUpdate(progress, ALL_APPS_PAGE_PROGRESS_INDEX);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWidgetsTransition(float progress) {
|
||||
super.onWidgetsTransition(progress);
|
||||
onTaskbarInAppDisplayProgressUpdate(progress, WIDGETS_PAGE_PROGRESS_INDEX);
|
||||
}
|
||||
|
||||
private void onTaskbarInAppDisplayProgressUpdate(float progress, int flag) {
|
||||
if (mTaskbarManager == null
|
||||
|| mTaskbarManager.getCurrentActivityContext() == null
|
||||
|| mTaskbarUIController == null) {
|
||||
return;
|
||||
}
|
||||
mTaskbarUIController.onTaskbarInAppDisplayProgressUpdate(progress, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -55,13 +55,13 @@ import com.android.launcher3.popup.SystemShortcut;
|
||||
import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.uioverrides.PredictedAppIcon;
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.views.Snackbar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -480,8 +480,8 @@ public class HotseatPredictionController implements DragController.DragListener,
|
||||
*
|
||||
* @param matcher filter matching items that have been removed
|
||||
*/
|
||||
public void onModelItemsRemoved(ItemInfoMatcher matcher) {
|
||||
if (mPredictedItems.removeIf(matcher::matchesInfo)) {
|
||||
public void onModelItemsRemoved(Predicate<ItemInfo> matcher) {
|
||||
if (mPredictedItems.removeIf(matcher)) {
|
||||
fillGapsWithPrediction(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,8 @@ public interface QuickstepSystemShortcut {
|
||||
|
||||
RecentsView recentsView = mTarget.getOverviewPanel();
|
||||
recentsView.initiateSplitSelect(
|
||||
new SplitSelectSource(view, new BitmapDrawable(bitmap), intent, mPosition));
|
||||
new SplitSelectSource(mOriginalView, new BitmapDrawable(bitmap), intent,
|
||||
mPosition));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -39,4 +39,10 @@ public class DesktopTaskbarUIController extends TaskbarUIController {
|
||||
protected void onDestroy() {
|
||||
mLauncher.getHotseat().setIconsAlpha(1f);
|
||||
}
|
||||
|
||||
@Override
|
||||
/** Disable taskbar stashing in desktop environment. */
|
||||
public boolean supportsVisualStashing() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.animation.Animator;
|
||||
import android.annotation.ColorInt;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.TaskTransitionSpec;
|
||||
import android.view.WindowManagerGlobal;
|
||||
@@ -43,6 +44,7 @@ import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
@@ -54,10 +56,22 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
|
||||
private static final String TAG = "TaskbarUIController";
|
||||
|
||||
public static final int MINUS_ONE_PAGE_PROGRESS_INDEX = 0;
|
||||
public static final int ALL_APPS_PAGE_PROGRESS_INDEX = 1;
|
||||
public static final int WIDGETS_PAGE_PROGRESS_INDEX = 2;
|
||||
public static final int SYSUI_SURFACE_PROGRESS_INDEX = 3;
|
||||
|
||||
private final SparseArray<Float> mTaskbarInAppDisplayProgress = new SparseArray<>(4);
|
||||
|
||||
private final BaseQuickstepLauncher mLauncher;
|
||||
|
||||
private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener =
|
||||
this::onStashedInAppChanged;
|
||||
dp -> {
|
||||
onStashedInAppChanged(dp);
|
||||
if (mControllers != null && mControllers.taskbarViewController != null) {
|
||||
mControllers.taskbarViewController.onRotationChanged(dp);
|
||||
}
|
||||
};
|
||||
|
||||
// Initialized in init.
|
||||
private AnimatedFloat mTaskbarOverrideBackgroundAlpha;
|
||||
@@ -65,15 +79,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
private final TaskbarLauncherStateController
|
||||
mTaskbarLauncherStateController = new TaskbarLauncherStateController();
|
||||
|
||||
private final DeviceProfile.OnDeviceProfileChangeListener mProfileChangeListener =
|
||||
new DeviceProfile.OnDeviceProfileChangeListener() {
|
||||
@Override
|
||||
public void onDeviceProfileChanged(DeviceProfile dp) {
|
||||
mControllers.taskbarViewController.onRotationChanged(
|
||||
mLauncher.getDeviceProfile());
|
||||
}
|
||||
};
|
||||
|
||||
public LauncherTaskbarUIController(BaseQuickstepLauncher launcher) {
|
||||
mLauncher = launcher;
|
||||
}
|
||||
@@ -93,7 +98,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
|
||||
onStashedInAppChanged(mLauncher.getDeviceProfile());
|
||||
mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
|
||||
mLauncher.addOnDeviceProfileChangeListener(mProfileChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -102,9 +106,8 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
onLauncherResumedOrPaused(false);
|
||||
mTaskbarLauncherStateController.onDestroy();
|
||||
|
||||
mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
|
||||
mLauncher.setTaskbarUIController(null);
|
||||
mLauncher.removeOnDeviceProfileChangeListener(mProfileChangeListener);
|
||||
mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener);
|
||||
updateTaskTransitionSpec(true);
|
||||
}
|
||||
|
||||
@@ -271,4 +274,85 @@ public class LauncherTaskbarUIController extends TaskbarUIController {
|
||||
// gesture ends, start drawing taskbar's background again since launcher might stop drawing.
|
||||
forceHideBackground(inProgress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates Taskbar elements during a transition to a Launcher state that should use in-app
|
||||
* layouts.
|
||||
*
|
||||
* @param progress [0, 1]
|
||||
* 0 => use home layout
|
||||
* 1 => use in-app layout
|
||||
*/
|
||||
public void onTaskbarInAppDisplayProgressUpdate(float progress, int progressIndex) {
|
||||
if (mControllers == null) {
|
||||
// This method can be called before init() is called.
|
||||
return;
|
||||
}
|
||||
mTaskbarInAppDisplayProgress.put(progressIndex, progress);
|
||||
if (!mControllers.taskbarStashController.isInApp()
|
||||
&& !mTaskbarLauncherStateController.isAnimatingToLauncher()) {
|
||||
// Only animate the nav buttons while home and not animating home, otherwise let
|
||||
// the TaskbarViewController handle it.
|
||||
mControllers.navbarButtonsViewController
|
||||
.getTaskbarNavButtonTranslationYForInAppDisplay()
|
||||
.updateValue(mLauncher.getDeviceProfile().getTaskbarOffsetY()
|
||||
* getInAppDisplayProgress());
|
||||
}
|
||||
}
|
||||
|
||||
/** Returns true iff any in-app display progress > 0. */
|
||||
public boolean shouldUseInAppLayout() {
|
||||
return getInAppDisplayProgress() > 0;
|
||||
}
|
||||
|
||||
private float getInAppDisplayProgress(int index) {
|
||||
if (!mTaskbarInAppDisplayProgress.contains(index)) {
|
||||
mTaskbarInAppDisplayProgress.put(index, 0f);
|
||||
}
|
||||
return mTaskbarInAppDisplayProgress.get(index);
|
||||
}
|
||||
|
||||
private float getInAppDisplayProgress() {
|
||||
return Stream.of(
|
||||
getInAppDisplayProgress(MINUS_ONE_PAGE_PROGRESS_INDEX),
|
||||
getInAppDisplayProgress(ALL_APPS_PAGE_PROGRESS_INDEX),
|
||||
getInAppDisplayProgress(WIDGETS_PAGE_PROGRESS_INDEX),
|
||||
getInAppDisplayProgress(SYSUI_SURFACE_PROGRESS_INDEX))
|
||||
.max(Float::compareTo)
|
||||
.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dumpLogs(String prefix, PrintWriter pw) {
|
||||
super.dumpLogs(prefix, pw);
|
||||
|
||||
pw.println(String.format(
|
||||
"%s\tmTaskbarOverrideBackgroundAlpha=%.2f",
|
||||
prefix,
|
||||
mTaskbarOverrideBackgroundAlpha.value));
|
||||
|
||||
pw.println(String.format("%s\tTaskbar in-app display progress:", prefix));
|
||||
if (mControllers == null) {
|
||||
pw.println(String.format("%s\t\tMissing mControllers", prefix));
|
||||
} else {
|
||||
pw.println(String.format(
|
||||
"%s\t\tprogress at MINUS_ONE_PAGE_PROGRESS_INDEX=%.2f",
|
||||
prefix,
|
||||
getInAppDisplayProgress(MINUS_ONE_PAGE_PROGRESS_INDEX)));
|
||||
pw.println(String.format(
|
||||
"%s\t\tprogress at ALL_APPS_PAGE_PROGRESS_INDEX=%.2f",
|
||||
prefix,
|
||||
getInAppDisplayProgress(ALL_APPS_PAGE_PROGRESS_INDEX)));
|
||||
pw.println(String.format(
|
||||
"%s\t\tprogress at WIDGETS_PAGE_PROGRESS_INDEX=%.2f",
|
||||
prefix,
|
||||
getInAppDisplayProgress(WIDGETS_PAGE_PROGRESS_INDEX)));
|
||||
pw.println(String.format(
|
||||
"%s\t\tprogress at SYSUI_SURFACE_PROGRESS_INDEX=%.2f",
|
||||
prefix,
|
||||
getInAppDisplayProgress(SYSUI_SURFACE_PROGRESS_INDEX)));
|
||||
}
|
||||
|
||||
mTaskbarLauncherStateController.dumpLogs(prefix + "\t", pw);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.android.launcher3.taskbar;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.taskbar.LauncherTaskbarUIController.SYSUI_SURFACE_PROGRESS_INDEX;
|
||||
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
|
||||
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
|
||||
import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
|
||||
@@ -126,11 +127,13 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
|
||||
private final AnimatedFloat mTaskbarNavButtonTranslationY = new AnimatedFloat(
|
||||
this::updateNavButtonTranslationY);
|
||||
private final AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay = new AnimatedFloat(
|
||||
this::updateNavButtonTranslationY);
|
||||
private final AnimatedFloat mTaskbarNavButtonTranslationYForIme = new AnimatedFloat(
|
||||
this::updateNavButtonTranslationY);
|
||||
// Only applies to mTaskbarNavButtonTranslationY
|
||||
private final AnimatedFloat mNavButtonTranslationYMultiplier = new AnimatedFloat(
|
||||
this::updateNavButtonTranslationY);
|
||||
// Used for System UI state updates that should translate the nav button for in-app display.
|
||||
private final AnimatedFloat mNavButtonInAppDisplayProgressForSysui = new AnimatedFloat(
|
||||
this::updateNavButtonInAppDisplayProgressForSysui);
|
||||
private final AnimatedFloat mTaskbarNavButtonDarkIntensity = new AnimatedFloat(
|
||||
this::updateNavButtonDarkIntensity);
|
||||
private final AnimatedFloat mNavButtonDarkIntensityMultiplier = new AnimatedFloat(
|
||||
@@ -173,7 +176,6 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
public void init(TaskbarControllers controllers) {
|
||||
mControllers = controllers;
|
||||
mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
|
||||
mNavButtonTranslationYMultiplier.value = 1;
|
||||
|
||||
boolean isThreeButtonNav = mContext.isThreeButtonNav();
|
||||
mIsImeRenderingNavButtons =
|
||||
@@ -205,9 +207,9 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
// Make sure to remove nav bar buttons translation when notification shade is expanded or
|
||||
// IME is showing (add separate translation for IME).
|
||||
int flagsToRemoveTranslation = FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_IME_VISIBLE;
|
||||
mPropertyHolders.add(new StatePropertyHolder(mNavButtonTranslationYMultiplier,
|
||||
mPropertyHolders.add(new StatePropertyHolder(mNavButtonInAppDisplayProgressForSysui,
|
||||
flags -> (flags & flagsToRemoveTranslation) != 0, AnimatedFloat.VALUE,
|
||||
0, 1));
|
||||
1, 0));
|
||||
// Center nav buttons in new height for IME.
|
||||
float transForIme = (mContext.getDeviceProfile().taskbarSize
|
||||
- mControllers.taskbarInsetsController.getTaskbarHeightForIme()) / 2f;
|
||||
@@ -526,6 +528,11 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
return mTaskbarNavButtonTranslationY;
|
||||
}
|
||||
|
||||
/** Use to set the translationY for the all nav+contextual buttons when in Launcher */
|
||||
public AnimatedFloat getTaskbarNavButtonTranslationYForInAppDisplay() {
|
||||
return mTaskbarNavButtonTranslationYForInAppDisplay;
|
||||
}
|
||||
|
||||
/** Use to set the dark intensity for the all nav+contextual buttons */
|
||||
public AnimatedFloat getTaskbarNavButtonDarkIntensity() {
|
||||
return mTaskbarNavButtonDarkIntensity;
|
||||
@@ -554,11 +561,26 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNavButtonInAppDisplayProgressForSysui() {
|
||||
TaskbarUIController uiController = mControllers.uiController;
|
||||
if (uiController instanceof LauncherTaskbarUIController) {
|
||||
((LauncherTaskbarUIController) uiController).onTaskbarInAppDisplayProgressUpdate(
|
||||
mNavButtonInAppDisplayProgressForSysui.value, SYSUI_SURFACE_PROGRESS_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNavButtonTranslationY() {
|
||||
float normalTranslationY = mTaskbarNavButtonTranslationY.value
|
||||
* mNavButtonTranslationYMultiplier.value;
|
||||
float otherTranslationY = mTaskbarNavButtonTranslationYForIme.value;
|
||||
mNavButtonsView.setTranslationY(normalTranslationY + otherTranslationY);
|
||||
final float normalTranslationY = mTaskbarNavButtonTranslationY.value;
|
||||
final float imeAdjustmentTranslationY = mTaskbarNavButtonTranslationYForIme.value;
|
||||
TaskbarUIController uiController = mControllers.uiController;
|
||||
final float inAppDisplayAdjustmentTranslationY =
|
||||
(uiController instanceof LauncherTaskbarUIController
|
||||
&& ((LauncherTaskbarUIController) uiController).shouldUseInAppLayout())
|
||||
? mTaskbarNavButtonTranslationYForInAppDisplay.value : 0;
|
||||
|
||||
mNavButtonsView.setTranslationY(normalTranslationY
|
||||
+ imeAdjustmentTranslationY
|
||||
+ inAppDisplayAdjustmentTranslationY);
|
||||
}
|
||||
|
||||
private void updateNavButtonDarkIntensity() {
|
||||
|
||||
@@ -199,7 +199,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
new TaskbarInsetsController(this));
|
||||
}
|
||||
|
||||
public void init(TaskbarSharedState sharedState) {
|
||||
public void init(@NonNull TaskbarSharedState sharedState) {
|
||||
mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight();
|
||||
mWindowLayoutParams = createDefaultWindowLayoutParams();
|
||||
|
||||
|
||||
@@ -61,6 +61,8 @@ public class TaskbarControllers {
|
||||
private boolean mAreAllControllersInitialized;
|
||||
private final List<Runnable> mPostInitCallbacks = new ArrayList<>();
|
||||
|
||||
@Nullable private TaskbarSharedState mSharedState = null;
|
||||
|
||||
public TaskbarControllers(TaskbarActivityContext taskbarActivityContext,
|
||||
TaskbarDragController taskbarDragController,
|
||||
TaskbarNavButtonController navButtonController,
|
||||
@@ -104,8 +106,9 @@ public class TaskbarControllers {
|
||||
* TaskbarControllers instance, but should be careful to only access things that were created
|
||||
* in constructors for now, as some controllers may still be waiting for init().
|
||||
*/
|
||||
public void init(TaskbarSharedState sharedState) {
|
||||
public void init(@NonNull TaskbarSharedState sharedState) {
|
||||
mAreAllControllersInitialized = false;
|
||||
mSharedState = sharedState;
|
||||
|
||||
taskbarDragController.init(this);
|
||||
navbarButtonsViewController.init(this);
|
||||
@@ -116,11 +119,11 @@ public class TaskbarControllers {
|
||||
taskbarUnfoldAnimationController.init(this);
|
||||
taskbarKeyguardController.init(navbarButtonsViewController);
|
||||
stashedHandleViewController.init(this);
|
||||
taskbarStashController.init(this, sharedState);
|
||||
taskbarStashController.init(this, sharedState.setupUIVisible);
|
||||
taskbarEduController.init(this);
|
||||
taskbarPopupController.init(this);
|
||||
taskbarForceVisibleImmersiveController.init(this);
|
||||
taskbarAllAppsController.init(this, sharedState);
|
||||
taskbarAllAppsController.init(this, sharedState.allAppsVisible);
|
||||
navButtonController.init(this);
|
||||
taskbarInsetsController.init(this);
|
||||
|
||||
@@ -139,6 +142,12 @@ public class TaskbarControllers {
|
||||
mPostInitCallbacks.clear();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TaskbarSharedState getSharedState() {
|
||||
// This should only be null if called before init() and after destroy().
|
||||
return mSharedState;
|
||||
}
|
||||
|
||||
public void onConfigurationChanged(@Config int configChanges) {
|
||||
navbarButtonsViewController.onConfigurationChanged(configChanges);
|
||||
}
|
||||
@@ -147,6 +156,8 @@ public class TaskbarControllers {
|
||||
* Cleans up all controllers.
|
||||
*/
|
||||
public void onDestroy() {
|
||||
mSharedState = null;
|
||||
|
||||
navbarButtonsViewController.onDestroy();
|
||||
uiController.onDestroy();
|
||||
rotationButtonController.onDestroy();
|
||||
@@ -187,9 +198,12 @@ public class TaskbarControllers {
|
||||
return;
|
||||
}
|
||||
|
||||
pw.println(String.format(
|
||||
"%s\tmAreAllControllersInitialized=%b", prefix, mAreAllControllersInitialized));
|
||||
for (LoggableTaskbarController controller : mControllersToLog) {
|
||||
controller.dumpLogs(prefix + "\t", pw);
|
||||
}
|
||||
uiController.dumpLogs(prefix + "\t", pw);
|
||||
rotationButtonController.dumpLogs(prefix + "\t", pw);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ import com.android.systemui.shared.recents.model.Task;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Handles long click on Taskbar items to start a system drag and drop operation.
|
||||
@@ -439,12 +440,12 @@ public class TaskbarDragController extends DragController<BaseTaskbarContext> im
|
||||
target = taskbarViewController.getAllAppsButtonView();
|
||||
} else if (item.container >= 0) {
|
||||
// Since folders close when the drag starts, target the folder icon instead.
|
||||
ItemInfoMatcher matcher = ItemInfoMatcher.forFolderMatch(
|
||||
Predicate<ItemInfo> matcher = ItemInfoMatcher.forFolderMatch(
|
||||
ItemInfoMatcher.ofItemIds(IntSet.wrap(item.id)));
|
||||
target = taskbarViewController.getFirstIconMatch(matcher);
|
||||
} else if (item.itemType == ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
// Find first icon with same package/user as the deep shortcut.
|
||||
ItemInfoMatcher packageUserMatcher = ItemInfoMatcher.ofPackages(
|
||||
Predicate<ItemInfo> packageUserMatcher = ItemInfoMatcher.ofPackages(
|
||||
Collections.singleton(item.getTargetPackage()), item.user);
|
||||
target = taskbarViewController.getFirstIconMatch(packageUserMatcher);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,9 @@ import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.animation.ViewRootSync;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.HashMap;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@@ -476,4 +478,48 @@ import java.util.function.Supplier;
|
||||
controller.applyState();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getStateString(int flags) {
|
||||
StringJoiner str = new StringJoiner("|");
|
||||
str.add((flags & FLAG_RESUMED) != 0 ? "FLAG_RESUMED" : "");
|
||||
str.add((flags & FLAG_RECENTS_ANIMATION_RUNNING) != 0
|
||||
? "FLAG_RECENTS_ANIMATION_RUNNING" : "");
|
||||
str.add((flags & FLAG_TRANSITION_STATE_RUNNING) != 0
|
||||
? "FLAG_TRANSITION_STATE_RUNNING" : "");
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
protected void dumpLogs(String prefix, PrintWriter pw) {
|
||||
pw.println(prefix + "TaskbarLauncherStateController:");
|
||||
|
||||
pw.println(String.format(
|
||||
"%s\tmIconAlignmentForResumedState=%.2f",
|
||||
prefix,
|
||||
mIconAlignmentForResumedState.value));
|
||||
pw.println(String.format(
|
||||
"%s\tmIconAlignmentForGestureState=%.2f",
|
||||
prefix,
|
||||
mIconAlignmentForGestureState.value));
|
||||
pw.println(String.format(
|
||||
"%s\tmIconAlignmentForLauncherState=%.2f",
|
||||
prefix,
|
||||
mIconAlignmentForLauncherState.value));
|
||||
pw.println(String.format(
|
||||
"%s\tmTaskbarBackgroundAlpha=%.2f", prefix, mTaskbarBackgroundAlpha.value));
|
||||
pw.println(String.format(
|
||||
"%s\tmIconAlphaForHome=%.2f", prefix, mIconAlphaForHome.getValue()));
|
||||
pw.println(String.format("%s\tmPrevState=%s", prefix, getStateString(mPrevState)));
|
||||
pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
|
||||
pw.println(String.format("%s\tmLauncherState=%s", prefix, mLauncherState));
|
||||
pw.println(String.format(
|
||||
"%s\tmIsAnimatingToLauncherViaGesture=%b",
|
||||
prefix,
|
||||
mIsAnimatingToLauncherViaGesture));
|
||||
pw.println(String.format(
|
||||
"%s\tmIsAnimatingToLauncherViaResume=%b",
|
||||
prefix,
|
||||
mIsAnimatingToLauncherViaResume));
|
||||
pw.println(String.format(
|
||||
"%s\tmShouldDelayLauncherStateAnim=%b", prefix, mShouldDelayLauncherStateAnim));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,6 +194,9 @@ public class TaskbarManager {
|
||||
* Sets a {@link StatefulActivity} to act as taskbar callback
|
||||
*/
|
||||
public void setActivity(@NonNull StatefulActivity activity) {
|
||||
if (mActivity == activity) {
|
||||
return;
|
||||
}
|
||||
mActivity = activity;
|
||||
mUnfoldProgressProvider.setSourceProvider(getUnfoldTransitionProgressProviderForActivity(
|
||||
activity));
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Launcher model Callbacks for rendering taskbar.
|
||||
@@ -126,16 +127,16 @@ public class TaskbarModelCallbacks implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) {
|
||||
public void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) {
|
||||
if (handleItemsRemoved(matcher)) {
|
||||
commitItemsToUI();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleItemsRemoved(ItemInfoMatcher matcher) {
|
||||
private boolean handleItemsRemoved(Predicate<ItemInfo> matcher) {
|
||||
boolean modified = false;
|
||||
for (int i = mHotseatItems.size() - 1; i >= 0; i--) {
|
||||
if (matcher.matchesInfo(mHotseatItems.valueAt(i))) {
|
||||
if (matcher.test(mHotseatItems.valueAt(i))) {
|
||||
modified = true;
|
||||
mHotseatItems.removeAt(i);
|
||||
}
|
||||
|
||||
@@ -25,5 +25,4 @@ public class TaskbarSharedState {
|
||||
public boolean setupUIVisible = false;
|
||||
|
||||
public boolean allAppsVisible = false;
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.android.launcher3.taskbar;
|
||||
|
||||
import static android.view.HapticFeedbackConstants.LONG_PRESS;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
|
||||
import static com.android.launcher3.taskbar.Utilities.appendFlag;
|
||||
@@ -34,7 +35,6 @@ import android.view.WindowInsets;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
@@ -167,7 +167,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
mStashedHeight = mActivity.getDeviceProfile().stashedTaskbarSize;
|
||||
}
|
||||
|
||||
public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) {
|
||||
public void init(TaskbarControllers controllers, boolean setupUIVisible) {
|
||||
mControllers = controllers;
|
||||
|
||||
TaskbarDragLayerController dragLayerController = controllers.taskbarDragLayerController;
|
||||
@@ -188,7 +188,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
|
||||
boolean isManuallyStashedInApp = supportsManualStashing()
|
||||
&& mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
|
||||
boolean isInSetup = !mActivity.isUserSetupComplete() || sharedState.setupUIVisible;
|
||||
boolean isInSetup = !mActivity.isUserSetupComplete() || setupUIVisible;
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
|
||||
updateStateForFlag(FLAG_IN_SETUP, isInSetup);
|
||||
@@ -202,7 +202,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
* state.
|
||||
*/
|
||||
public boolean supportsVisualStashing() {
|
||||
return !mActivity.isThreeButtonNav();
|
||||
return mControllers.uiController.supportsVisualStashing();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,7 +275,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
return !mIsStashed && isInApp();
|
||||
}
|
||||
|
||||
private boolean isInApp() {
|
||||
public boolean isInApp() {
|
||||
return hasAnyFlag(FLAGS_IN_APP);
|
||||
}
|
||||
|
||||
@@ -564,7 +564,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_ALL_APPS, false);
|
||||
if (applyState) {
|
||||
applyState(TaskbarAllAppsSlideInView.DEFAULT_CLOSE_DURATION);
|
||||
applyState(ALL_APPS.getTransitionDuration(
|
||||
mControllers.taskbarActivityContext, false /* isToState */));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import androidx.annotation.CallSuper;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
@@ -48,6 +49,11 @@ public class TaskbarUIController {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean supportsVisualStashing() {
|
||||
if (mControllers == null) return false;
|
||||
return !mControllers.taskbarActivityContext.isThreeButtonNav();
|
||||
}
|
||||
|
||||
protected void onStashedInAppChanged() { }
|
||||
|
||||
public Stream<ItemInfoWithIcon> getAppIconsForEdu() {
|
||||
@@ -86,4 +92,12 @@ public class TaskbarUIController {
|
||||
stashController.applyState();
|
||||
}
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
protected void dumpLogs(String prefix, PrintWriter pw) {
|
||||
pw.println(String.format(
|
||||
"%sTaskbarUIController: using an instance of %s",
|
||||
prefix,
|
||||
getClass().getSimpleName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,12 +41,13 @@ import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.uioverrides.ApiWrapper;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.LauncherBindableItemsContainer;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.AllAppsButton;
|
||||
import com.android.launcher3.views.DoubleShadowBubbleTextView;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Hosts the Taskbar content such as Hotseat and Recent Apps. Drawn on top of other apps.
|
||||
*/
|
||||
@@ -424,8 +425,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
* Finds the first icon to match one of the given matchers, from highest to lowest priority.
|
||||
* @return The first match, or All Apps button if no match was found.
|
||||
*/
|
||||
public View getFirstMatch(ItemInfoMatcher... matchers) {
|
||||
for (ItemInfoMatcher matcher : matchers) {
|
||||
public View getFirstMatch(Predicate<ItemInfo>... matchers) {
|
||||
for (Predicate<ItemInfo> matcher : matchers) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View item = getChildAt(i);
|
||||
if (!(item.getTag() instanceof ItemInfo)) {
|
||||
@@ -433,7 +434,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar
|
||||
continue;
|
||||
}
|
||||
ItemInfo info = (ItemInfo) item.getTag();
|
||||
if (matcher.matchesInfo(info)) {
|
||||
if (matcher.test(info)) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.android.launcher3.util.MultiValueAlpha;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Handles properties/data collection, then passes the results to TaskbarView to render.
|
||||
@@ -73,6 +74,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
private final AnimatedFloat mTaskbarIconTranslationYForStash = new AnimatedFloat(
|
||||
this::updateTranslationY);
|
||||
private AnimatedFloat mTaskbarNavButtonTranslationY;
|
||||
private AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay;
|
||||
|
||||
private final AnimatedFloat mThemeIconsBackground = new AnimatedFloat(
|
||||
this::updateIconsBackground);
|
||||
@@ -112,6 +114,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
}
|
||||
mTaskbarNavButtonTranslationY =
|
||||
controllers.navbarButtonsViewController.getTaskbarNavButtonTranslationY();
|
||||
mTaskbarNavButtonTranslationYForInAppDisplay = controllers.navbarButtonsViewController
|
||||
.getTaskbarNavButtonTranslationYForInAppDisplay();
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
@@ -242,6 +246,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
int offsetY = launcherDp.getTaskbarOffsetY();
|
||||
setter.setFloat(mTaskbarIconTranslationYForHome, VALUE, -offsetY, LINEAR);
|
||||
setter.setFloat(mTaskbarNavButtonTranslationY, VALUE, -offsetY, LINEAR);
|
||||
setter.setFloat(mTaskbarNavButtonTranslationYForInAppDisplay, VALUE, offsetY, LINEAR);
|
||||
|
||||
if (Utilities.isDarkTheme(mTaskbarView.getContext())) {
|
||||
setter.addFloat(mThemeIconsBackground, VALUE, 0f, 1f, LINEAR);
|
||||
@@ -258,12 +263,14 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
View child = mTaskbarView.getChildAt(i);
|
||||
|
||||
int positionInHotseat = -1;
|
||||
if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get() && i == count - 1) {
|
||||
boolean isRtl = Utilities.isRtl(child.getResources());
|
||||
if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()
|
||||
&& ((isRtl && i == 0) || (!isRtl && i == count - 1))) {
|
||||
// Note that there is no All Apps button in the hotseat, this position is only used
|
||||
// as its convenient for animation purposes.
|
||||
positionInHotseat = Utilities.isRtl(child.getResources())
|
||||
positionInHotseat = isRtl
|
||||
? -1
|
||||
: mActivity.getDeviceProfile().inv.numShownHotseatIcons;
|
||||
: mActivity.getDeviceProfile().numShownHotseatIcons;
|
||||
|
||||
setter.setViewAlpha(child, 0, LINEAR);
|
||||
} else if (child.getTag() instanceof ItemInfo) {
|
||||
@@ -289,10 +296,12 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
}
|
||||
|
||||
public void onRotationChanged(DeviceProfile deviceProfile) {
|
||||
if (areIconsVisible()) {
|
||||
if (mControllers.taskbarStashController.isInApp()) {
|
||||
// We only translate on rotation when on home
|
||||
return;
|
||||
}
|
||||
mActivity.setTaskbarWindowHeight(
|
||||
deviceProfile.taskbarSize + deviceProfile.getTaskbarOffsetY());
|
||||
mTaskbarNavButtonTranslationY.updateValue(-deviceProfile.getTaskbarOffsetY());
|
||||
}
|
||||
|
||||
@@ -309,8 +318,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar
|
||||
* 2) FolderIcon of the Folder containing the given icon
|
||||
* 3) All Apps button
|
||||
*/
|
||||
public View getFirstIconMatch(ItemInfoMatcher matcher) {
|
||||
ItemInfoMatcher folderMatcher = ItemInfoMatcher.forFolderMatch(matcher);
|
||||
public View getFirstIconMatch(Predicate<ItemInfo> matcher) {
|
||||
Predicate<ItemInfo> folderMatcher = ItemInfoMatcher.forFolderMatch(matcher);
|
||||
return mTaskbarView.getFirstMatch(matcher, folderMatcher);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.taskbar.TaskbarActivityContext;
|
||||
import com.android.launcher3.taskbar.TaskbarControllers;
|
||||
import com.android.launcher3.taskbar.TaskbarSharedState;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListeners;
|
||||
|
||||
@@ -72,7 +71,6 @@ public final class TaskbarAllAppsController implements OnDeviceProfileChangeList
|
||||
};
|
||||
|
||||
private TaskbarControllers mControllers;
|
||||
private TaskbarSharedState mSharedState;
|
||||
/** Window context for all apps if it is open. */
|
||||
private @Nullable TaskbarAllAppsContext mAllAppsContext;
|
||||
|
||||
@@ -88,18 +86,17 @@ public final class TaskbarAllAppsController implements OnDeviceProfileChangeList
|
||||
}
|
||||
|
||||
/** Initialize the controller. */
|
||||
public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) {
|
||||
public void init(TaskbarControllers controllers, boolean allAppsVisible) {
|
||||
if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
|
||||
return;
|
||||
}
|
||||
mControllers = controllers;
|
||||
mSharedState = sharedState;
|
||||
|
||||
/*
|
||||
* Recreate All Apps if it was open in the previous Taskbar instance (e.g. the configuration
|
||||
* changed).
|
||||
*/
|
||||
if (mSharedState.allAppsVisible) {
|
||||
if (allAppsVisible) {
|
||||
show(false);
|
||||
}
|
||||
}
|
||||
@@ -141,7 +138,9 @@ public final class TaskbarAllAppsController implements OnDeviceProfileChangeList
|
||||
return;
|
||||
}
|
||||
mProxyView.show();
|
||||
mSharedState.allAppsVisible = true;
|
||||
// mControllers and getSharedState should never be null here. Do not handle null-pointer
|
||||
// to catch invalid states.
|
||||
mControllers.getSharedState().allAppsVisible = true;
|
||||
|
||||
mAllAppsContext = new TaskbarAllAppsContext(mTaskbarContext,
|
||||
this,
|
||||
@@ -176,7 +175,9 @@ public final class TaskbarAllAppsController implements OnDeviceProfileChangeList
|
||||
return;
|
||||
}
|
||||
mProxyView.close(false);
|
||||
mSharedState.allAppsVisible = false;
|
||||
// mControllers and getSharedState should never be null here. Do not handle null-pointer
|
||||
// to catch invalid states.
|
||||
mControllers.getSharedState().allAppsVisible = false;
|
||||
onDestroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,16 @@
|
||||
*/
|
||||
package com.android.launcher3.taskbar.allapps;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
|
||||
import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
|
||||
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Insettable;
|
||||
@@ -33,9 +36,6 @@ import java.util.Optional;
|
||||
/** Wrapper for taskbar all apps with slide-in behavior. */
|
||||
public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarAllAppsContext>
|
||||
implements Insettable, DeviceProfile.OnDeviceProfileChangeListener {
|
||||
static final int DEFAULT_OPEN_DURATION = 500;
|
||||
public static final int DEFAULT_CLOSE_DURATION = 200;
|
||||
|
||||
private TaskbarAllAppsContainerView mAppsView;
|
||||
private OnCloseListener mOnCloseBeginListener;
|
||||
private float mShiftRange;
|
||||
@@ -61,7 +61,8 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarAllApp
|
||||
mOpenCloseAnimator.setValues(
|
||||
PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
|
||||
mOpenCloseAnimator.setInterpolator(AGGRESSIVE_EASE);
|
||||
mOpenCloseAnimator.setDuration(DEFAULT_OPEN_DURATION).start();
|
||||
mOpenCloseAnimator.setDuration(
|
||||
ALL_APPS.getTransitionDuration(mContext, true /* isToState */)).start();
|
||||
} else {
|
||||
mTranslationShift = TRANSLATION_SHIFT_OPENED;
|
||||
}
|
||||
@@ -80,7 +81,12 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarAllApp
|
||||
@Override
|
||||
protected void handleClose(boolean animate) {
|
||||
Optional.ofNullable(mOnCloseBeginListener).ifPresent(OnCloseListener::onSlideInViewClosed);
|
||||
handleClose(animate, DEFAULT_CLOSE_DURATION);
|
||||
handleClose(animate, ALL_APPS.getTransitionDuration(mContext, false /* isToState */));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Interpolator getIdleInterpolator() {
|
||||
return EMPHASIZED_ACCELERATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+3
-2
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.android.launcher3.taskbar.allapps;
|
||||
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_APP_ALL_APPS;
|
||||
import static com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView.DEFAULT_OPEN_DURATION;
|
||||
import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
@@ -81,7 +81,8 @@ final class TaskbarAllAppsViewController {
|
||||
|
||||
private void setUpTaskbarStashing() {
|
||||
mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_APP_ALL_APPS, true);
|
||||
mTaskbarStashController.applyState(DEFAULT_OPEN_DURATION);
|
||||
mTaskbarStashController.applyState(
|
||||
ALL_APPS.getTransitionDuration(mContext, true /* isToState */));
|
||||
mSlideInView.setOnCloseBeginListener(() -> {
|
||||
AbstractFloatingView.closeOpenContainer(
|
||||
mContext, AbstractFloatingView.TYPE_ACTION_POPUP);
|
||||
|
||||
@@ -70,7 +70,6 @@ import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchT
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.TwoButtonNavbarTouchController;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.DisplayController.NavigationMode;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.PendingRequestArgs;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.util.UiThreadHelper;
|
||||
@@ -86,6 +85,7 @@ import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class QuickstepLauncher extends BaseQuickstepLauncher {
|
||||
@@ -245,7 +245,7 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) {
|
||||
public void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) {
|
||||
super.bindWorkspaceComponentsRemoved(matcher);
|
||||
mHotseatPredictionController.onModelItemsRemoved(matcher);
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public final class RecentsViewStateController extends
|
||||
if (toState == OVERVIEW_SPLIT_SELECT) {
|
||||
// Animation to "dismiss" selected taskView
|
||||
PendingAnimation splitSelectInitAnimation = mRecentsView.createSplitSelectInitAnimation(
|
||||
toState.getTransitionDuration(mLauncher));
|
||||
toState.getTransitionDuration(mLauncher, true /* isToState */));
|
||||
// Add properties to shift remaining taskViews to get out of placeholder view
|
||||
splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.first,
|
||||
toState.getSplitSelectTranslation(mLauncher), LINEAR);
|
||||
|
||||
@@ -33,12 +33,12 @@ import com.android.systemui.shared.plugins.PluginInstance;
|
||||
import com.android.systemui.shared.plugins.PluginManager;
|
||||
import com.android.systemui.shared.plugins.PluginManagerImpl;
|
||||
import com.android.systemui.shared.plugins.PluginPrefs;
|
||||
import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public class PluginManagerWrapper {
|
||||
@@ -48,6 +48,9 @@ public class PluginManagerWrapper {
|
||||
|
||||
public static final String PLUGIN_CHANGED = PluginManager.PLUGIN_CHANGED;
|
||||
|
||||
private static final UncaughtExceptionPreHandlerManager UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER =
|
||||
new UncaughtExceptionPreHandlerManager();
|
||||
|
||||
private final Context mContext;
|
||||
private final PluginManager mPluginManager;
|
||||
private final PluginEnablerImpl mPluginEnabler;
|
||||
@@ -67,7 +70,7 @@ public class PluginManagerWrapper {
|
||||
|
||||
mPluginManager = new PluginManagerImpl(c, instanceManagerFactory,
|
||||
Utilities.IS_DEBUG_DEVICE,
|
||||
Optional.ofNullable(Thread.getDefaultUncaughtExceptionHandler()), mPluginEnabler,
|
||||
UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER, mPluginEnabler,
|
||||
new PluginPrefs(c), privilegedPlugins);
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@ public class AllAppsState extends LauncherState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransitionDuration(Context context) {
|
||||
return 150;
|
||||
public int getTransitionDuration(Context context, boolean isToState) {
|
||||
return isToState ? 500 : 300;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -40,7 +40,7 @@ public class OverviewModalTaskState extends OverviewState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransitionDuration(Context launcher) {
|
||||
public int getTransitionDuration(Context launcher, boolean isToState) {
|
||||
return 300;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,10 +22,12 @@ import android.content.Context;
|
||||
import android.graphics.Rect;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.taskbar.LauncherTaskbarUIController;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
@@ -56,7 +58,7 @@ public class OverviewState extends LauncherState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransitionDuration(Context context) {
|
||||
public int getTransitionDuration(Context context, boolean isToState) {
|
||||
// In gesture modes, overview comes in all the way from the side, so give it more time.
|
||||
return DisplayController.getNavigationMode(context).hasGestures ? 380 : 250;
|
||||
}
|
||||
@@ -93,7 +95,13 @@ public class OverviewState extends LauncherState {
|
||||
|
||||
@Override
|
||||
public boolean isTaskbarStashed(Launcher launcher) {
|
||||
return true;
|
||||
if (launcher instanceof BaseQuickstepLauncher) {
|
||||
LauncherTaskbarUIController uiController =
|
||||
((BaseQuickstepLauncher) launcher).getTaskbarUIController();
|
||||
|
||||
return uiController != null && uiController.supportsVisualStashing();
|
||||
}
|
||||
return super.isTaskbarStashed(launcher);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+12
-4
@@ -42,6 +42,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SC
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||
@@ -50,6 +51,8 @@ import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesT
|
||||
import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_OPAQUE_THRESHOLD;
|
||||
import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_VISIBLE_THRESHOLD;
|
||||
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
|
||||
import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE;
|
||||
import static com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE;
|
||||
|
||||
import android.animation.ValueAnimator;
|
||||
|
||||
@@ -179,12 +182,17 @@ public class QuickstepAtomicAnimationFactory extends
|
||||
}
|
||||
config.duration = Math.max(config.duration, mHintToNormalDuration);
|
||||
} else if (fromState == ALL_APPS && toState == NORMAL) {
|
||||
config.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
|
||||
1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
|
||||
1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
|
||||
config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL,
|
||||
boolean isTablet = mActivity.getDeviceProfile().isTablet;
|
||||
config.setInterpolator(ANIM_ALL_APPS_FADE,
|
||||
isTablet ? FINAL_FRAME : Interpolators.clampToProgress(LINEAR,
|
||||
1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
|
||||
1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
|
||||
config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(LINEAR,
|
||||
1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
|
||||
1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
|
||||
config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_ACCELERATE);
|
||||
} else if (fromState == NORMAL && toState == ALL_APPS) {
|
||||
config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_DECELERATE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -180,7 +180,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
|
||||
// Normally we compute the duration based on the velocity and distance to the given
|
||||
// state, but since the hint state tracks the entire screen without a clear endpoint, we
|
||||
// need to manually set the duration to a reasonable value.
|
||||
animator.setDuration(HINT_STATE.getTransitionDuration(mLauncher));
|
||||
animator.setDuration(HINT_STATE.getTransitionDuration(mLauncher, true /* isToState */));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-6
@@ -21,10 +21,9 @@ import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
|
||||
|
||||
@@ -131,10 +130,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
||||
boolean isTablet = mLauncher.getDeviceProfile().isTablet;
|
||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
|
||||
? INSTANT
|
||||
: Interpolators.clampToProgress(ACCEL,
|
||||
: Interpolators.clampToProgress(LINEAR,
|
||||
ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD,
|
||||
ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD));
|
||||
builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(ACCEL,
|
||||
builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(LINEAR,
|
||||
ALL_APPS_SCRIM_VISIBLE_THRESHOLD,
|
||||
ALL_APPS_SCRIM_OPAQUE_THRESHOLD));
|
||||
return builder;
|
||||
@@ -145,10 +144,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
||||
boolean isTablet = mLauncher.getDeviceProfile().isTablet;
|
||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
|
||||
? FINAL_FRAME
|
||||
: Interpolators.clampToProgress(DEACCEL,
|
||||
: Interpolators.clampToProgress(LINEAR,
|
||||
1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
|
||||
1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
|
||||
builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL,
|
||||
builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(LINEAR,
|
||||
1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
|
||||
1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
|
||||
return builder;
|
||||
|
||||
@@ -104,8 +104,7 @@ public class RecentsAnimationCallbacks implements
|
||||
.map(RemoteAnimationTargetCompat::unwrap)
|
||||
.toArray(RemoteAnimationTarget[]::new);
|
||||
|
||||
RemoteAnimationTarget[] nonAppTargets =
|
||||
mSystemUiProxy.onGoingToRecentsLegacy(mCancelled, nonHomeApps);
|
||||
RemoteAnimationTarget[] nonAppTargets = mSystemUiProxy.onGoingToRecentsLegacy(nonHomeApps);
|
||||
|
||||
RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
|
||||
wallpaperTargets, RemoteAnimationTargetCompat.wrap(nonAppTargets),
|
||||
|
||||
@@ -676,14 +676,12 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
|
||||
* Call this when going to recents so that shell can set-up and provide appropriate leashes
|
||||
* for animation (eg. DividerBar).
|
||||
*
|
||||
* @param cancel true if recents starting is being cancelled.
|
||||
* @return RemoteAnimationTargets of windows that need to animate but only exist in shell.
|
||||
*/
|
||||
public RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel,
|
||||
RemoteAnimationTarget[] apps) {
|
||||
public RemoteAnimationTarget[] onGoingToRecentsLegacy(RemoteAnimationTarget[] apps) {
|
||||
if (mSplitScreen != null) {
|
||||
try {
|
||||
return mSplitScreen.onGoingToRecentsLegacy(cancel, apps);
|
||||
return mSplitScreen.onGoingToRecentsLegacy(apps);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call onGoingToRecentsLegacy");
|
||||
}
|
||||
@@ -691,6 +689,17 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
|
||||
return null;
|
||||
}
|
||||
|
||||
public RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) {
|
||||
if (mSplitScreen != null) {
|
||||
try {
|
||||
return mSplitScreen.onStartingSplitLegacy(apps);
|
||||
} catch (RemoteException e) {
|
||||
Log.w(TAG, "Failed call onStartingSplitLegacy");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// One handed
|
||||
//
|
||||
|
||||
@@ -177,8 +177,9 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
((RecentsActivity) activityInterface.getCreatedActivity()).startHome();
|
||||
return;
|
||||
}
|
||||
RemoteAnimationTarget[] nonAppTargets = SystemUiProxy.INSTANCE.get(mCtx)
|
||||
.onGoingToRecentsLegacy(false, nonHomeApps);
|
||||
|
||||
RemoteAnimationTarget[] nonAppTargets =
|
||||
SystemUiProxy.INSTANCE.getNoCreate().onStartingSplitLegacy(nonHomeApps);
|
||||
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
|
||||
&& activityInterface.getCreatedActivity() != null) {
|
||||
|
||||
@@ -112,7 +112,7 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
|
||||
RecentsState currentState = mActivity.getStateManager().getState();
|
||||
if (isSplitSelectionState(state) && !isSplitSelectionState(currentState)) {
|
||||
setter.add(mRecentsView.createSplitSelectInitAnimation(
|
||||
state.getTransitionDuration(mActivity)).buildAnim());
|
||||
state.getTransitionDuration(mActivity, true /* isToState */)).buildAnim());
|
||||
}
|
||||
|
||||
Pair<FloatProperty, FloatProperty> taskViewsFloat =
|
||||
|
||||
@@ -77,7 +77,7 @@ public class RecentsState implements BaseState<RecentsState> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransitionDuration(Context context) {
|
||||
public int getTransitionDuration(Context context, boolean isToState) {
|
||||
return 250;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ public class OverviewToHomeAnim {
|
||||
// WorkspaceRevealAnim handles the depth, so don't interfere.
|
||||
config.animFlags |= StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
|
||||
}
|
||||
config.duration = startState.getTransitionDuration(mLauncher);
|
||||
config.duration = startState.getTransitionDuration(mLauncher, false /* isToState */);
|
||||
AnimatorSet stateAnim = stateManager.createAtomicAnimation(
|
||||
startState, NORMAL, config);
|
||||
stateAnim.addListener(new AnimationSuccessListener() {
|
||||
|
||||
@@ -196,6 +196,13 @@ public class FloatingTaskView extends FrameLayout {
|
||||
0, 1, ACCEL);
|
||||
animation.addFloat(mThumbnailView, LauncherAnimUtils.VIEW_ALPHA,
|
||||
1, 0, DEACCEL_3);
|
||||
} else if (isStagedTask) {
|
||||
// Fade in the placeholder view when split is initiated from homescreen / all apps
|
||||
// icons.
|
||||
if (mSplitPlaceholderView.getAlpha() == 0) {
|
||||
animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT,
|
||||
0.3f, 1, ACCEL);
|
||||
}
|
||||
}
|
||||
|
||||
MultiValueUpdateListener listener = new MultiValueUpdateListener() {
|
||||
|
||||
@@ -2757,16 +2757,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
mSplitHiddenTaskView.getThumbnail().getThumbnail(),
|
||||
mSplitHiddenTaskView.getIconView().getDrawable(), startingTaskRect);
|
||||
mFirstFloatingTaskView.setAlpha(1);
|
||||
mFirstFloatingTaskView.addAnimation(anim, startingTaskRect,
|
||||
mTempRect, true /* fadeWithThumbnail */, true /* isStagedTask */);
|
||||
mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
|
||||
true /* fadeWithThumbnail */, true /* isStagedTask */);
|
||||
} else {
|
||||
mSplitSelectSource.view.setVisibility(INVISIBLE);
|
||||
mFirstFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
|
||||
mSplitSelectSource.view, null,
|
||||
mSplitSelectSource.view, null /* thumbnail */,
|
||||
mSplitSelectSource.drawable, startingTaskRect);
|
||||
mFirstFloatingTaskView.setAlpha(1);
|
||||
mFirstFloatingTaskView.addAnimation(anim, startingTaskRect,
|
||||
mTempRect, true /* fadeWithThumbnail */, true /* isStagedTask */);
|
||||
mFirstFloatingTaskView.addAnimation(anim, startingTaskRect, mTempRect,
|
||||
false /* fadeWithThumbnail */, true /* isStagedTask */);
|
||||
}
|
||||
InteractionJankMonitorWrapper.begin(this,
|
||||
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER, "First tile selected");
|
||||
@@ -4059,7 +4058,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
// TODO(194414938) starting bounds seem slightly off, investigate
|
||||
Rect firstTaskStartingBounds = new Rect();
|
||||
Rect firstTaskEndingBounds = mTempRect;
|
||||
int duration = mActivity.getStateManager().getState().getTransitionDuration(getContext());
|
||||
int duration = mActivity.getStateManager().getState().getTransitionDuration(getContext(),
|
||||
false /* isToState */);
|
||||
PendingAnimation pendingAnimation = new PendingAnimation(duration);
|
||||
|
||||
int halfDividerSize = getResources()
|
||||
|
||||
@@ -182,7 +182,6 @@ import com.android.launcher3.util.ActivityTracker;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.OnboardingPrefs;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
@@ -2739,9 +2738,9 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
*/
|
||||
public View getFirstMatchForAppClose(int preferredItemId, String packageName, UserHandle user,
|
||||
boolean supportsAllAppsState) {
|
||||
final ItemInfoMatcher preferredItem = (info, cn) ->
|
||||
final Predicate<ItemInfo> preferredItem = info ->
|
||||
info != null && info.id == preferredItemId;
|
||||
final ItemInfoMatcher packageAndUserAndApp = (info, cn) ->
|
||||
final Predicate<ItemInfo> packageAndUserAndApp = info ->
|
||||
info != null
|
||||
&& info.itemType == ITEM_TYPE_APPLICATION
|
||||
&& info.user.equals(user)
|
||||
@@ -2770,8 +2769,8 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
* @param operators List of operators, in order starting from best matching operator.
|
||||
*/
|
||||
private static View getFirstMatch(Iterable<ViewGroup> containers,
|
||||
final ItemInfoMatcher... operators) {
|
||||
for (ItemInfoMatcher operator : operators) {
|
||||
final Predicate<ItemInfo>... operators) {
|
||||
for (Predicate<ItemInfo> operator : operators) {
|
||||
for (ViewGroup container : containers) {
|
||||
View match = mapOverViewGroup(container, operator);
|
||||
if (match != null) {
|
||||
@@ -2786,11 +2785,11 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
* Returns the first view matching the operator in the given ViewGroups, or null if none.
|
||||
* Forward iteration matters.
|
||||
*/
|
||||
private static View mapOverViewGroup(ViewGroup container, ItemInfoMatcher op) {
|
||||
private static View mapOverViewGroup(ViewGroup container, Predicate<ItemInfo> op) {
|
||||
final int itemCount = container.getChildCount();
|
||||
for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) {
|
||||
View item = container.getChildAt(itemIdx);
|
||||
if (op.matchesInfo((ItemInfo) item.getTag())) {
|
||||
if (op.test((ItemInfo) item.getTag())) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
@@ -2887,7 +2886,7 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
* package-removal should clear all items by package name.
|
||||
*/
|
||||
@Override
|
||||
public void bindWorkspaceComponentsRemoved(final ItemInfoMatcher matcher) {
|
||||
public void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) {
|
||||
mWorkspace.removeItemsByMatcher(matcher);
|
||||
mDragController.onAppsRemoved(matcher);
|
||||
PopupContainerWithArrow.dismissInvalidPopup(this);
|
||||
@@ -3168,6 +3167,24 @@ public class Launcher extends StatefulActivity<LauncherState>
|
||||
return new DragOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates Launcher elements during a transition to the All Apps page.
|
||||
*
|
||||
* @param progress Transition progress from 0 to 1; where 0 => home and 1 => all apps.
|
||||
*/
|
||||
public void onAllAppsTransition(float progress) {
|
||||
// No-Op
|
||||
}
|
||||
|
||||
/**
|
||||
* Animates Launcher elements during a transition to the Widgets pages.
|
||||
*
|
||||
* @param progress Transition progress from 0 to 1; where 0 => home and 1 => widgets.
|
||||
*/
|
||||
public void onWidgetsTransition(float progress) {
|
||||
// No-Op
|
||||
}
|
||||
|
||||
private static class NonConfigInstance {
|
||||
public Configuration config;
|
||||
public Bitmap snapshot;
|
||||
|
||||
@@ -113,7 +113,7 @@ public abstract class LauncherState implements BaseState<LauncherState> {
|
||||
FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON |
|
||||
FLAG_HAS_SYS_UI_SCRIM) {
|
||||
@Override
|
||||
public int getTransitionDuration(Context context) {
|
||||
public int getTransitionDuration(Context context, boolean isToState) {
|
||||
// Arbitrary duration, when going to NORMAL we use the state we're coming from instead.
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -31,6 +31,10 @@ public class ResourceUtils {
|
||||
public static final String NAVBAR_HEIGHT = "navigation_bar_height";
|
||||
public static final String NAVBAR_HEIGHT_LANDSCAPE = "navigation_bar_height_landscape";
|
||||
|
||||
public static final String STATUS_BAR_HEIGHT = "status_bar_height";
|
||||
public static final String STATUS_BAR_HEIGHT_LANDSCAPE = "status_bar_height_landscape";
|
||||
public static final String STATUS_BAR_HEIGHT_PORTRAIT = "status_bar_height_portrait";
|
||||
|
||||
public static int getNavbarSize(String resName, Resources res) {
|
||||
return getDimenByName(resName, res, DEFAULT_NAVBAR_VALUE);
|
||||
}
|
||||
|
||||
@@ -102,7 +102,6 @@ import com.android.launcher3.util.Executors;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.IntSparseArrayMap;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.LauncherBindableItemsContainer;
|
||||
import com.android.launcher3.util.OverlayEdgeEffect;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
@@ -2118,7 +2117,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
|
||||
final Runnable onCompleteCallback = onCompleteRunnable;
|
||||
mLauncher.getDragController().animateDragViewToOriginalPosition(
|
||||
/* onComplete= */ callbackList::executeAllAndDestroy, cell,
|
||||
SPRING_LOADED.getTransitionDuration(mLauncher));
|
||||
SPRING_LOADED.getTransitionDuration(mLauncher, true /* isToState */));
|
||||
mLauncher.getStateManager().goToState(NORMAL, /* delay= */ 0,
|
||||
onCompleteCallback == null
|
||||
? null
|
||||
@@ -3235,7 +3234,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
|
||||
* as a part of an update, this is called to ensure that other widgets and application
|
||||
* shortcuts are not removed.
|
||||
*/
|
||||
public void removeItemsByMatcher(final ItemInfoMatcher matcher) {
|
||||
public void removeItemsByMatcher(final Predicate<ItemInfo> matcher) {
|
||||
for (CellLayout layout : getWorkspaceAndHotseatCellLayouts()) {
|
||||
ShortcutAndWidgetContainer container = layout.getShortcutsAndWidgets();
|
||||
// Iterate in reverse order as we are removing items
|
||||
@@ -3243,7 +3242,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
|
||||
View child = container.getChildAt(i);
|
||||
ItemInfo info = (ItemInfo) child.getTag();
|
||||
|
||||
if (matcher.matchesInfo(info)) {
|
||||
if (matcher.test(info)) {
|
||||
layout.removeViewInLayout(child);
|
||||
if (child instanceof DropTarget) {
|
||||
mDragController.removeDropTarget((DropTarget) child);
|
||||
@@ -3251,7 +3250,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
|
||||
} else if (child instanceof FolderIcon) {
|
||||
FolderInfo folderInfo = (FolderInfo) info;
|
||||
List<WorkspaceItemInfo> matches = folderInfo.contents.stream()
|
||||
.filter(matcher::matchesInfo)
|
||||
.filter(matcher)
|
||||
.collect(Collectors.toList());
|
||||
if (!matches.isEmpty()) {
|
||||
folderInfo.removeAll(matches, false);
|
||||
@@ -3330,7 +3329,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T>
|
||||
*
|
||||
* @param matcher the matcher generated by the caller.
|
||||
*/
|
||||
public void persistRemoveItemsByMatcher(ItemInfoMatcher matcher) {
|
||||
public void persistRemoveItemsByMatcher(Predicate<ItemInfo> matcher) {
|
||||
mLauncher.getModelWriter().deleteItemsFromDatabase(matcher);
|
||||
removeItemsByMatcher(matcher);
|
||||
}
|
||||
|
||||
@@ -190,6 +190,7 @@ public class AllAppsTransitionController
|
||||
public void setProgress(float progress) {
|
||||
mProgress = progress;
|
||||
getAppsViewProgressTranslationY().set(mAppsView, mProgress * mShiftRange);
|
||||
mLauncher.onAllAppsTransition(1 - progress);
|
||||
}
|
||||
|
||||
public float getProgress() {
|
||||
@@ -254,8 +255,6 @@ public class AllAppsTransitionController
|
||||
anim.setInterpolator(verticalProgressInterpolator);
|
||||
anim.addListener(getProgressAnimatorListener());
|
||||
builder.add(anim);
|
||||
// Use ANIM_VERTICAL_PROGRESS's interpolator to determine state transition threshold.
|
||||
builder.setInterpolator(verticalProgressInterpolator);
|
||||
|
||||
setAlphas(toState, config, builder);
|
||||
|
||||
|
||||
@@ -21,17 +21,18 @@ import android.content.Context;
|
||||
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.LabelComparator;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* The alphabetically sorted list of applications.
|
||||
@@ -82,7 +83,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
|
||||
private AppInfoComparator mAppNameComparator;
|
||||
private final int mNumAppsPerRowAllApps;
|
||||
private int mNumAppRowsInAdapter;
|
||||
private ItemInfoMatcher mItemFilter;
|
||||
private Predicate<ItemInfo> mItemFilter;
|
||||
|
||||
public AlphabeticalAppsList(Context context, AllAppsStore appsStore,
|
||||
WorkAdapterProvider adapterProvider) {
|
||||
@@ -94,7 +95,7 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
|
||||
mAllAppsStore.addUpdateListener(this);
|
||||
}
|
||||
|
||||
public void updateItemFilter(ItemInfoMatcher itemFilter) {
|
||||
public void updateItemFilter(Predicate<ItemInfo> itemFilter) {
|
||||
this.mItemFilter = itemFilter;
|
||||
onAppsUpdated();
|
||||
}
|
||||
@@ -200,13 +201,11 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
|
||||
// Sort the list of apps
|
||||
mApps.clear();
|
||||
|
||||
for (AppInfo app : mAllAppsStore.getApps()) {
|
||||
if (mItemFilter == null || mItemFilter.matches(app, null) || hasFilter()) {
|
||||
mApps.add(app);
|
||||
}
|
||||
Stream<AppInfo> appSteam = Stream.of(mAllAppsStore.getApps());
|
||||
if (!hasFilter() && mItemFilter != null) {
|
||||
appSteam = appSteam.filter(mItemFilter);
|
||||
}
|
||||
|
||||
Collections.sort(mApps, mAppNameComparator);
|
||||
appSteam = appSteam.sorted(mAppNameComparator);
|
||||
|
||||
// As a special case for some languages (currently only Simplified Chinese), we may need to
|
||||
// coalesce sections
|
||||
@@ -215,27 +214,16 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
|
||||
if (localeRequiresSectionSorting) {
|
||||
// Compute the section headers. We use a TreeMap with the section name comparator to
|
||||
// ensure that the sections are ordered when we iterate over it later
|
||||
TreeMap<String, ArrayList<AppInfo>> sectionMap = new TreeMap<>(new LabelComparator());
|
||||
for (AppInfo info : mApps) {
|
||||
// Add the section to the cache
|
||||
String sectionName = info.sectionName;
|
||||
|
||||
// Add it to the mapping
|
||||
ArrayList<AppInfo> sectionApps = sectionMap.get(sectionName);
|
||||
if (sectionApps == null) {
|
||||
sectionApps = new ArrayList<>();
|
||||
sectionMap.put(sectionName, sectionApps);
|
||||
}
|
||||
sectionApps.add(info);
|
||||
}
|
||||
|
||||
// Add each of the section apps to the list in order
|
||||
mApps.clear();
|
||||
for (Map.Entry<String, ArrayList<AppInfo>> entry : sectionMap.entrySet()) {
|
||||
mApps.addAll(entry.getValue());
|
||||
}
|
||||
appSteam = appSteam.collect(Collectors.groupingBy(
|
||||
info -> info.sectionName,
|
||||
() -> new TreeMap<>(new LabelComparator()),
|
||||
Collectors.toCollection(ArrayList::new)))
|
||||
.values()
|
||||
.stream()
|
||||
.flatMap(ArrayList::stream);
|
||||
}
|
||||
|
||||
appSteam.forEachOrdered(mApps::add);
|
||||
// Recompose the set of adapter items from the current set of apps
|
||||
if (mSearchResults.isEmpty()) {
|
||||
updateAdapterItems();
|
||||
|
||||
@@ -58,7 +58,7 @@ import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.search.SearchAdapterProvider;
|
||||
import com.android.launcher3.keyboard.FocusedItemDecorator;
|
||||
import com.android.launcher3.model.StringCache;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
@@ -69,6 +69,8 @@ import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePag
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Base all apps view container.
|
||||
@@ -91,7 +93,7 @@ public abstract class BaseAllAppsContainerView<T extends Context & ActivityConte
|
||||
/** Context of an activity or window that is inflating this container. */
|
||||
protected final T mActivityContext;
|
||||
protected final List<AdapterHolder> mAH;
|
||||
protected final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser(
|
||||
protected final Predicate<ItemInfo> mPersonalMatcher = ItemInfoMatcher.ofUser(
|
||||
Process.myUserHandle());
|
||||
private final SearchAdapterProvider<?> mMainAdapterProvider;
|
||||
private final AllAppsStore mAllAppsStore = new AllAppsStore();
|
||||
@@ -229,17 +231,10 @@ public abstract class BaseAllAppsContainerView<T extends Context & ActivityConte
|
||||
}
|
||||
|
||||
private void onAppsUpdated() {
|
||||
boolean hasWorkApps = false;
|
||||
for (AppInfo app : mAllAppsStore.getApps()) {
|
||||
if (mWorkManager.getMatcher().matches(app, null)) {
|
||||
hasWorkApps = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
mHasWorkApps = hasWorkApps;
|
||||
mHasWorkApps = Stream.of(mAllAppsStore.getApps()).anyMatch(mWorkManager.getMatcher());
|
||||
if (!mAH.get(AdapterHolder.MAIN).mAppsList.hasFilter()) {
|
||||
rebindAdapters();
|
||||
if (hasWorkApps) {
|
||||
if (mHasWorkApps) {
|
||||
mWorkManager.reset();
|
||||
}
|
||||
}
|
||||
@@ -731,7 +726,7 @@ public abstract class BaseAllAppsContainerView<T extends Context & ActivityConte
|
||||
mLayoutManager = adapter.getLayoutManager();
|
||||
}
|
||||
|
||||
void setup(@NonNull View rv, @Nullable ItemInfoMatcher matcher) {
|
||||
void setup(@NonNull View rv, @Nullable Predicate<ItemInfo> matcher) {
|
||||
mAppsList.updateItemFilter(matcher);
|
||||
mRecyclerView = (AllAppsRecyclerView) rv;
|
||||
mRecyclerView.setEdgeEffectFactory(createEdgeEffectFactory());
|
||||
|
||||
@@ -27,7 +27,6 @@ import android.os.UserHandle;
|
||||
import android.os.UserManager;
|
||||
import android.util.Log;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -35,11 +34,12 @@ import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Companion class for {@link BaseAllAppsContainerView} to manage work tab and personal tab
|
||||
@@ -70,7 +70,7 @@ public class WorkProfileManager implements PersonalWorkSlidingTabStrip.OnActiveP
|
||||
|
||||
private final BaseAllAppsContainerView<?> mAllApps;
|
||||
private final WorkAdapterProvider mAdapterProvider;
|
||||
private final ItemInfoMatcher mMatcher;
|
||||
private final Predicate<ItemInfo> mMatcher;
|
||||
|
||||
private WorkModeSwitch mWorkModeSwitch;
|
||||
|
||||
@@ -176,7 +176,7 @@ public class WorkProfileManager implements PersonalWorkSlidingTabStrip.OnActiveP
|
||||
return mAdapterProvider;
|
||||
}
|
||||
|
||||
public ItemInfoMatcher getMatcher() {
|
||||
public Predicate<ItemInfo> getMatcher() {
|
||||
return mMatcher;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,13 +47,6 @@ public class Interpolators {
|
||||
public static final Interpolator DEACCEL_2_5 = new DecelerateInterpolator(2.5f);
|
||||
public static final Interpolator DEACCEL_3 = new DecelerateInterpolator(3f);
|
||||
|
||||
/**
|
||||
* The decelerating emphasized interpolator. Used for hero / emphasized movement of content that
|
||||
* is appearing e.g. when coming from off screen
|
||||
*/
|
||||
public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator(
|
||||
0.05f, 0.7f, 0.1f, 1f);
|
||||
|
||||
public static final Interpolator ACCEL_DEACCEL = new AccelerateDecelerateInterpolator();
|
||||
|
||||
public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
|
||||
|
||||
@@ -18,7 +18,6 @@ package com.android.launcher3.dragndrop;
|
||||
|
||||
import static com.android.launcher3.Utilities.ATLEAST_Q;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -36,12 +35,12 @@ import com.android.launcher3.logging.InstanceId;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Class for initiating a drag within a view or across multiple views.
|
||||
@@ -275,15 +274,12 @@ public abstract class DragController<T extends ActivityContext>
|
||||
|
||||
protected abstract void exitDrag();
|
||||
|
||||
public void onAppsRemoved(ItemInfoMatcher matcher) {
|
||||
public void onAppsRemoved(Predicate<ItemInfo> matcher) {
|
||||
// Cancel the current drag if we are removing an app that we are dragging
|
||||
if (mDragObject != null) {
|
||||
ItemInfo dragInfo = mDragObject.dragInfo;
|
||||
if (dragInfo instanceof WorkspaceItemInfo) {
|
||||
ComponentName cn = dragInfo.getTargetComponent();
|
||||
if (cn != null && matcher.matches(dragInfo, cn)) {
|
||||
cancelDrag();
|
||||
}
|
||||
if (dragInfo instanceof WorkspaceItemInfo && matcher.test(dragInfo)) {
|
||||
cancelDrag();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,8 @@ class PinShortcutRequestActivityInfo extends ShortcutConfigActivityInfo {
|
||||
// Total duration for the drop animation to complete.
|
||||
long duration = mContext.getResources().getInteger(R.integer.config_dropAnimMaxDuration) +
|
||||
LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY +
|
||||
LauncherState.SPRING_LOADED.getTransitionDuration(Launcher.getLauncher(mContext));
|
||||
LauncherState.SPRING_LOADED.getTransitionDuration(Launcher.getLauncher(mContext),
|
||||
true /* isToState */);
|
||||
// Delay the actual accept() call until the drop animation is complete.
|
||||
return PinRequestHelper.createWorkspaceItemFromPinItemRequest(
|
||||
mContext, mRequest, duration);
|
||||
|
||||
@@ -36,9 +36,9 @@ import com.android.launcher3.compat.AlphabeticIndexCompat;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.BgDataModel.Callbacks;
|
||||
import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.pm.PackageInstallInfo;
|
||||
import com.android.launcher3.util.FlagOp;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.util.SafeCloseable;
|
||||
|
||||
@@ -47,6 +47,7 @@ import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
|
||||
/**
|
||||
@@ -257,11 +258,11 @@ public class AllAppsList {
|
||||
/**
|
||||
* Updates the disabled flags of apps matching {@param matcher} based on {@param op}.
|
||||
*/
|
||||
public void updateDisabledFlags(ItemInfoMatcher matcher, FlagOp op) {
|
||||
public void updateDisabledFlags(Predicate<ItemInfo> matcher, FlagOp op) {
|
||||
final List<AppInfo> data = this.data;
|
||||
for (int i = data.size() - 1; i >= 0; i--) {
|
||||
AppInfo info = data.get(i);
|
||||
if (matcher.matches(info, info.componentName)) {
|
||||
if (matcher.test(info)) {
|
||||
info.runtimeStatusFlags = op.apply(info.runtimeStatusFlags);
|
||||
mDataChanged = true;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.android.launcher3.model.data.AppInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -35,6 +34,7 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -128,7 +128,7 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask {
|
||||
scheduleCallbackTask(c -> c.bindAllWidgets(widgets));
|
||||
}
|
||||
|
||||
public void deleteAndBindComponentsRemoved(final ItemInfoMatcher matcher) {
|
||||
public void deleteAndBindComponentsRemoved(final Predicate<ItemInfo> matcher) {
|
||||
getModelWriter().deleteItemsFromDatabase(matcher);
|
||||
|
||||
// Call the components-removed callback
|
||||
|
||||
@@ -50,7 +50,6 @@ import com.android.launcher3.util.ComponentKey;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
import com.android.launcher3.util.IntSet;
|
||||
import com.android.launcher3.util.IntSparseArrayMap;
|
||||
import com.android.launcher3.util.ItemInfoMatcher;
|
||||
import com.android.launcher3.util.RunnableList;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
|
||||
@@ -66,6 +65,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -495,7 +495,7 @@ public class BgDataModel {
|
||||
default void bindWorkspaceItemsChanged(List<WorkspaceItemInfo> updated) { }
|
||||
default void bindWidgetsRestored(ArrayList<LauncherAppWidgetInfo> widgets) { }
|
||||
default void bindRestoreItemsChange(HashSet<ItemInfo> updates) { }
|
||||
default void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) { }
|
||||
default void bindWorkspaceComponentsRemoved(Predicate<ItemInfo> matcher) { }
|
||||
default void bindAllWidgets(List<WidgetsListBaseEntry> widgets) { }
|
||||
|
||||
default void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) {
|
||||
|
||||
@@ -53,6 +53,7 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
@@ -278,10 +279,9 @@ public class ModelWriter {
|
||||
/**
|
||||
* Removes all the items from the database matching {@param matcher}.
|
||||
*/
|
||||
public void deleteItemsFromDatabase(ItemInfoMatcher matcher) {
|
||||
public void deleteItemsFromDatabase(Predicate<ItemInfo> matcher) {
|
||||
deleteItemsFromDatabase(StreamSupport.stream(mBgDataModel.itemsIdMap.spliterator(), false)
|
||||
.filter(matcher::matchesInfo)
|
||||
.collect(Collectors.toList()));
|
||||
.filter(matcher).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,6 +57,7 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* Handles updates due to changes in package manager (app installed/updated/removed)
|
||||
@@ -95,7 +96,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
||||
final int N = packages.length;
|
||||
final FlagOp flagOp;
|
||||
final HashSet<String> packageSet = new HashSet<>(Arrays.asList(packages));
|
||||
final ItemInfoMatcher matcher = mOp == OP_USER_AVAILABILITY_CHANGE
|
||||
final Predicate<ItemInfo> matcher = mOp == OP_USER_AVAILABILITY_CHANGE
|
||||
? ItemInfoMatcher.ofUser(mUser) // We want to update all packages for this user
|
||||
: ItemInfoMatcher.ofPackages(packageSet, mUser);
|
||||
final HashSet<ComponentName> removedComponents = new HashSet<>();
|
||||
@@ -206,7 +207,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
||||
}
|
||||
|
||||
ComponentName cn = si.getTargetComponent();
|
||||
if (cn != null && matcher.matches(si, cn)) {
|
||||
if (cn != null && matcher.test(si)) {
|
||||
String packageName = cn.getPackageName();
|
||||
|
||||
if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)) {
|
||||
@@ -336,7 +337,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask {
|
||||
}
|
||||
|
||||
if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) {
|
||||
ItemInfoMatcher removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser)
|
||||
Predicate<ItemInfo> removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser)
|
||||
.or(ItemInfoMatcher.ofComponents(removedComponents, mUser))
|
||||
.and(ItemInfoMatcher.ofItemIds(forceKeepShortcuts).negate());
|
||||
deleteAndBindComponentsRemoved(removeMatch);
|
||||
|
||||
@@ -36,7 +36,7 @@ public interface BaseState<T extends BaseState> {
|
||||
/**
|
||||
* @return How long the animation to this state should take (or from this state to NORMAL).
|
||||
*/
|
||||
int getTransitionDuration(Context context);
|
||||
int getTransitionDuration(Context context, boolean isToState);
|
||||
|
||||
/**
|
||||
* Returns the state to go back to from this state
|
||||
|
||||
@@ -253,8 +253,8 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
|
||||
// Since state mBaseState can be reached from multiple states, just assume that the
|
||||
// transition plays in reverse and use the same duration as previous state.
|
||||
mConfig.duration = state == mBaseState
|
||||
? fromState.getTransitionDuration(mActivity)
|
||||
: state.getTransitionDuration(mActivity);
|
||||
? fromState.getTransitionDuration(mActivity, false /* isToState */)
|
||||
: state.getTransitionDuration(mActivity, true /* isToState */);
|
||||
prepareForAtomicAnimation(fromState, state, mConfig);
|
||||
AnimatorSet animation = createAnimationToNewWorkspaceInternal(state).buildAnim();
|
||||
if (listener != null) {
|
||||
|
||||
@@ -43,7 +43,7 @@ public class HintState extends LauncherState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransitionDuration(Context context) {
|
||||
public int getTransitionDuration(Context context, boolean isToState) {
|
||||
return 80;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ public class SpringLoadedState extends LauncherState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransitionDuration(Context context) {
|
||||
public int getTransitionDuration(Context context, boolean isToState) {
|
||||
return 150;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ package com.android.launcher3.util;
|
||||
import android.content.ComponentName;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.LauncherSettings.Favorites;
|
||||
import com.android.launcher3.model.data.FolderInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
@@ -27,90 +29,64 @@ import com.android.launcher3.shortcuts.ShortcutKey;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
* A utility class to check for {@link ItemInfo}
|
||||
*/
|
||||
public interface ItemInfoMatcher {
|
||||
public abstract class ItemInfoMatcher {
|
||||
|
||||
/**
|
||||
* Empty component used for match testing
|
||||
*/
|
||||
ComponentName EMPTY_COMPONENT = new ComponentName("", "");
|
||||
private static final ComponentName EMPTY_COMPONENT = new ComponentName("", "");
|
||||
|
||||
boolean matches(ItemInfo info, ComponentName cn);
|
||||
|
||||
/**
|
||||
* Returns true if the itemInfo matches this check
|
||||
*/
|
||||
default boolean matchesInfo(ItemInfo info) {
|
||||
if (info != null) {
|
||||
ComponentName cn = info.getTargetComponent();
|
||||
return matches(info, cn != null ? cn : EMPTY_COMPONENT);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
public static Predicate<ItemInfo> ofUser(UserHandle user) {
|
||||
return info -> info != null && info.user.equals(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new matcher with returns true if either this or {@param matcher} returns true.
|
||||
*/
|
||||
default ItemInfoMatcher or(ItemInfoMatcher matcher) {
|
||||
return (info, cn) -> matches(info, cn) || matcher.matches(info, cn);
|
||||
public static Predicate<ItemInfo> ofComponents(
|
||||
HashSet<ComponentName> components, UserHandle user) {
|
||||
return info -> info != null && info.user.equals(user)
|
||||
&& components.contains(getNonNullComponent(info));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new matcher with returns true if both this and {@param matcher} returns true.
|
||||
*/
|
||||
default ItemInfoMatcher and(ItemInfoMatcher matcher) {
|
||||
return (info, cn) -> matches(info, cn) && matcher.matches(info, cn);
|
||||
public static Predicate<ItemInfo> ofPackages(Set<String> packageNames, UserHandle user) {
|
||||
return info -> info != null && info.user.equals(user)
|
||||
&& packageNames.contains(getNonNullComponent(info).getPackageName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new matcher with returns the opposite value of this.
|
||||
*/
|
||||
default ItemInfoMatcher negate() {
|
||||
return (info, cn) -> !matches(info, cn);
|
||||
}
|
||||
|
||||
static ItemInfoMatcher ofUser(UserHandle user) {
|
||||
return (info, cn) -> info.user.equals(user);
|
||||
}
|
||||
|
||||
static ItemInfoMatcher ofComponents(HashSet<ComponentName> components, UserHandle user) {
|
||||
return (info, cn) -> components.contains(cn) && info.user.equals(user);
|
||||
}
|
||||
|
||||
static ItemInfoMatcher ofPackages(Set<String> packageNames, UserHandle user) {
|
||||
return (info, cn) -> packageNames.contains(cn.getPackageName()) && info.user.equals(user);
|
||||
}
|
||||
|
||||
static ItemInfoMatcher ofShortcutKeys(Set<ShortcutKey> keys) {
|
||||
return (info, cn) -> info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
|
||||
public static Predicate<ItemInfo> ofShortcutKeys(Set<ShortcutKey> keys) {
|
||||
return info -> info != null && info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT
|
||||
&& keys.contains(ShortcutKey.fromItemInfo(info));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a matcher for items within folders.
|
||||
*/
|
||||
static ItemInfoMatcher forFolderMatch(ItemInfoMatcher childOperator) {
|
||||
return (info, cn) -> info instanceof FolderInfo && ((FolderInfo) info).contents.stream()
|
||||
.anyMatch(childOperator::matchesInfo);
|
||||
public static Predicate<ItemInfo> forFolderMatch(Predicate<ItemInfo> childOperator) {
|
||||
return info -> info instanceof FolderInfo && ((FolderInfo) info).contents.stream()
|
||||
.anyMatch(childOperator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a matcher for items with provided ids
|
||||
*/
|
||||
static ItemInfoMatcher ofItemIds(IntSet ids) {
|
||||
return (info, cn) -> ids.contains(info.id);
|
||||
public static Predicate<ItemInfo> ofItemIds(IntSet ids) {
|
||||
return info -> info != null && ids.contains(info.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a matcher for items with provided items
|
||||
*/
|
||||
static ItemInfoMatcher ofItems(Collection<? extends ItemInfo> items) {
|
||||
public static Predicate<ItemInfo> ofItems(Collection<? extends ItemInfo> items) {
|
||||
IntSet ids = new IntSet();
|
||||
items.forEach(item -> ids.add(item.id));
|
||||
return ofItemIds(ids);
|
||||
}
|
||||
|
||||
private static ComponentName getNonNullComponent(@NonNull ItemInfo info) {
|
||||
ComponentName cn = info.getTargetComponent();
|
||||
return cn != null ? cn : EMPTY_COMPONENT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE;
|
||||
import static com.android.launcher3.ResourceUtils.NAVBAR_HEIGHT;
|
||||
import static com.android.launcher3.ResourceUtils.NAVBAR_HEIGHT_LANDSCAPE;
|
||||
import static com.android.launcher3.ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE;
|
||||
import static com.android.launcher3.ResourceUtils.STATUS_BAR_HEIGHT;
|
||||
import static com.android.launcher3.ResourceUtils.STATUS_BAR_HEIGHT_LANDSCAPE;
|
||||
import static com.android.launcher3.ResourceUtils.STATUS_BAR_HEIGHT_PORTRAIT;
|
||||
import static com.android.launcher3.Utilities.dpiFromPx;
|
||||
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
|
||||
import static com.android.launcher3.util.RotationUtils.deltaRotation;
|
||||
@@ -152,20 +155,26 @@ public class WindowManagerProxy implements ResourceBasedOverride {
|
||||
|
||||
boolean isTablet = config.smallestScreenWidthDp > MIN_TABLET_WIDTH;
|
||||
boolean isGesture = isGestureNav(context);
|
||||
boolean isPortrait = config.screenHeightDp > config.screenWidthDp;
|
||||
|
||||
int bottomNav = isTablet
|
||||
? 0
|
||||
: (config.screenHeightDp > config.screenWidthDp
|
||||
? getDimenByName(NAVBAR_HEIGHT, systemRes)
|
||||
: (isPortrait
|
||||
? getDimenByName(systemRes, NAVBAR_HEIGHT)
|
||||
: (isGesture
|
||||
? getDimenByName(NAVBAR_HEIGHT_LANDSCAPE, systemRes)
|
||||
? getDimenByName(systemRes, NAVBAR_HEIGHT_LANDSCAPE)
|
||||
: 0));
|
||||
Insets newNavInsets = Insets.of(navInsets.left, navInsets.top, navInsets.right, bottomNav);
|
||||
insetsBuilder.setInsets(WindowInsets.Type.navigationBars(), newNavInsets);
|
||||
insetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(), newNavInsets);
|
||||
|
||||
Insets statusBarInsets = oldInsets.getInsets(WindowInsets.Type.statusBars());
|
||||
int statusBarHeight = getDimenByName("status_bar_height", systemRes);
|
||||
|
||||
|
||||
int statusBarHeight = getDimenByName(systemRes,
|
||||
(isPortrait) ? STATUS_BAR_HEIGHT_PORTRAIT : STATUS_BAR_HEIGHT_LANDSCAPE,
|
||||
STATUS_BAR_HEIGHT);
|
||||
|
||||
Insets newStatusBarInsets = Insets.of(
|
||||
statusBarInsets.left,
|
||||
Math.max(statusBarInsets.top, statusBarHeight),
|
||||
@@ -221,23 +230,26 @@ public class WindowManagerProxy implements ResourceBasedOverride {
|
||||
boolean isTabletOrGesture = isTablet
|
||||
|| (Utilities.ATLEAST_R && isGestureNav(context));
|
||||
|
||||
int statusBarHeight = getDimenByName("status_bar_height", systemRes);
|
||||
int statusBarHeightPortrait = getDimenByName(systemRes,
|
||||
STATUS_BAR_HEIGHT_PORTRAIT, STATUS_BAR_HEIGHT);
|
||||
int statusBarHeightLandscape = getDimenByName(systemRes,
|
||||
STATUS_BAR_HEIGHT_LANDSCAPE, STATUS_BAR_HEIGHT);
|
||||
|
||||
int navBarHeightPortrait, navBarHeightLandscape, navbarWidthLandscape;
|
||||
|
||||
navBarHeightPortrait = isTablet
|
||||
? (mTaskbarDrawnInProcess
|
||||
? 0 : systemRes.getDimensionPixelSize(R.dimen.taskbar_size))
|
||||
: getDimenByName(NAVBAR_HEIGHT, systemRes);
|
||||
: getDimenByName(systemRes, NAVBAR_HEIGHT);
|
||||
|
||||
navBarHeightLandscape = isTablet
|
||||
? (mTaskbarDrawnInProcess
|
||||
? 0 : systemRes.getDimensionPixelSize(R.dimen.taskbar_size))
|
||||
: (isTabletOrGesture
|
||||
? getDimenByName(NAVBAR_HEIGHT_LANDSCAPE, systemRes) : 0);
|
||||
? getDimenByName(systemRes, NAVBAR_HEIGHT_LANDSCAPE) : 0);
|
||||
navbarWidthLandscape = isTabletOrGesture
|
||||
? 0
|
||||
: getDimenByName(NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE, systemRes);
|
||||
: getDimenByName(systemRes, NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE);
|
||||
|
||||
WindowBounds[] result = new WindowBounds[4];
|
||||
Point tempSize = new Point();
|
||||
@@ -247,13 +259,15 @@ public class WindowManagerProxy implements ResourceBasedOverride {
|
||||
rotateSize(tempSize, rotationChange);
|
||||
Rect bounds = new Rect(0, 0, tempSize.x, tempSize.y);
|
||||
|
||||
int navBarHeight, navbarWidth;
|
||||
int navBarHeight, navbarWidth, statusBarHeight;
|
||||
if (tempSize.y > tempSize.x) {
|
||||
navBarHeight = navBarHeightPortrait;
|
||||
navbarWidth = 0;
|
||||
statusBarHeight = statusBarHeightPortrait;
|
||||
} else {
|
||||
navBarHeight = navBarHeightLandscape;
|
||||
navbarWidth = navbarWidthLandscape;
|
||||
statusBarHeight = statusBarHeightLandscape;
|
||||
}
|
||||
|
||||
Rect insets = new Rect(safeCutout);
|
||||
@@ -276,10 +290,18 @@ public class WindowManagerProxy implements ResourceBasedOverride {
|
||||
/**
|
||||
* Wrapper around the utility method for easier emulation
|
||||
*/
|
||||
protected int getDimenByName(String resName, Resources res) {
|
||||
protected int getDimenByName(Resources res, String resName) {
|
||||
return ResourceUtils.getDimenByName(resName, res, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around the utility method for easier emulation
|
||||
*/
|
||||
protected int getDimenByName(Resources res, String resName, String fallback) {
|
||||
int dimen = ResourceUtils.getDimenByName(resName, res, -1);
|
||||
return dimen > -1 ? dimen : getDimenByName(res, fallback);
|
||||
}
|
||||
|
||||
protected boolean isGestureNav(Context context) {
|
||||
return ResourceUtils.getIntegerByName("config_navBarInteractionMode",
|
||||
context.getResources(), INVALID_RESOURCE_HANDLE) == 2;
|
||||
|
||||
@@ -231,13 +231,17 @@ public abstract class AbstractSlideInView<T extends Context & ActivityContext>
|
||||
if (mSwipeDetector.isIdleState()) {
|
||||
mOpenCloseAnimator
|
||||
.setDuration(defaultDuration)
|
||||
.setInterpolator(Interpolators.ACCEL);
|
||||
.setInterpolator(getIdleInterpolator());
|
||||
} else {
|
||||
mOpenCloseAnimator.setInterpolator(mScrollInterpolator);
|
||||
}
|
||||
mOpenCloseAnimator.start();
|
||||
}
|
||||
|
||||
protected Interpolator getIdleInterpolator() {
|
||||
return Interpolators.ACCEL;
|
||||
}
|
||||
|
||||
protected void onCloseComplete() {
|
||||
mIsOpen = false;
|
||||
getPopupContainer().removeView(this);
|
||||
|
||||
@@ -44,6 +44,7 @@ import com.android.launcher3.touch.ItemLongClickListener;
|
||||
import com.android.launcher3.util.SystemUiController;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.AbstractSlideInView;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.ArrowTipView;
|
||||
|
||||
/**
|
||||
@@ -306,4 +307,11 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
|
||||
return mActivityContext.getSharedPrefs().getBoolean(KEY_WIDGETS_EDUCATION_TIP_SEEN, false)
|
||||
|| Utilities.IS_RUNNING_IN_TEST_HARNESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setTranslationShift(float translationShift) {
|
||||
super.setTranslationShift(translationShift);
|
||||
Launcher launcher = ActivityContext.lookupContext(getContext());
|
||||
launcher.onWidgetsTransition(1 - translationShift);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ public class AllAppsState extends LauncherState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransitionDuration(Context context) {
|
||||
return 320;
|
||||
public int getTransitionDuration(Context context, boolean isToState) {
|
||||
return isToState ? 500 : 300;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -34,7 +34,7 @@ public class OverviewState extends LauncherState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTransitionDuration(Context context) {
|
||||
public int getTransitionDuration(Context context, boolean isToState) {
|
||||
return 250;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,9 +43,14 @@ public class TestWindowManagerProxy extends WindowManagerProxy {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDimenByName(String resName, Resources res) {
|
||||
protected int getDimenByName(Resources res, String resName) {
|
||||
Integer mock = mDevice.resourceOverrides.get(resName);
|
||||
return mock != null ? mock : super.getDimenByName(resName, res);
|
||||
return mock != null ? mock : super.getDimenByName(res, resName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDimenByName(Resources res, String resName, String fallback) {
|
||||
return getDimenByName(res, resName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user