Change wallpaper depth in widget picker

- Also changed widget picker open/close duration, refactored the values into DeviceProfile
- Generalized MultiAdditivePropertyFactory to accept aggregator as parameter

Bug: 240580498
Test: manual
Change-Id: I6886ca514593e404b8d7b0e8ed44f20ec2b77c73
This commit is contained in:
Alex Chau 2022-09-01 21:28:14 +01:00
parent a7be354913
commit 3d2c062567
19 changed files with 169 additions and 69 deletions

View File

@ -43,4 +43,9 @@
<!-- Accessibility actions -->
<item type="id" name="action_move_to_top_or_left" />
<item type="id" name="action_move_to_bottom_or_right" />
<!-- The max scale for the wallpaper when it's zoomed in -->
<item name="config_wallpaperMaxScale" format="float" type="dimen">
@*android:dimen/config_wallpaperMaxScale
</item>
</resources>

View File

@ -42,7 +42,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_SCRIM_FOR_APP_LAU
import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.launcher3.statehandlers.DepthController.STATE_DEPTH;
import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
import static com.android.launcher3.views.FloatingIconView.getFloatingIconView;
@ -384,7 +384,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
@Override
public void onAnimationStart(Animator animation) {
mLauncher.addOnResumeCallback(() ->
ObjectAnimator.ofFloat(mLauncher.getDepthController(), DEPTH,
ObjectAnimator.ofFloat(mLauncher.getDepthController(), STATE_DEPTH,
mLauncher.getStateManager().getState().getDepth(
mLauncher)).start());
}
@ -408,7 +408,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
@Override
public void onAnimationStart(Animator animation) {
mLauncher.addOnResumeCallback(() ->
ObjectAnimator.ofFloat(mLauncher.getDepthController(), DEPTH,
ObjectAnimator.ofFloat(mLauncher.getDepthController(), STATE_DEPTH,
mLauncher.getStateManager().getState().getDepth(
mLauncher)).start());
}
@ -1051,7 +1051,7 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
&& BlurUtils.supportsBlursOnWindows();
MyDepthController depthController = new MyDepthController(mLauncher);
ObjectAnimator backgroundRadiusAnim = ObjectAnimator.ofFloat(depthController, DEPTH,
ObjectAnimator backgroundRadiusAnim = ObjectAnimator.ofFloat(depthController, STATE_DEPTH,
BACKGROUND_APP.getDepth(mLauncher))
.setDuration(APP_LAUNCH_DURATION);
@ -1594,7 +1594,8 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
true /* animateOverviewScrim */, launcherView).getAnimators());
if (!areAllTargetsTranslucent(appTargets)) {
anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController(), DEPTH,
anim.play(ObjectAnimator.ofFloat(mLauncher.getDepthController(),
STATE_DEPTH,
BACKGROUND_APP.getDepth(mLauncher), NORMAL.getDepth(mLauncher)));
}

View File

@ -165,7 +165,8 @@ public class DepthController extends BaseDepthController implements StateHandler
float toDepth = toState.getDepth(mLauncher);
if (Float.compare(mDepth, toDepth) != 0) {
animation.setFloat(this, DEPTH, toDepth, config.getInterpolator(ANIM_DEPTH, LINEAR));
animation.setFloat(this, STATE_DEPTH, toDepth,
config.getInterpolator(ANIM_DEPTH, LINEAR));
}
}
@ -179,7 +180,7 @@ public class DepthController extends BaseDepthController implements StateHandler
public void onMultiWindowModeChanged(boolean isInMultiWindowMode) {
mIgnoreStateChangesDuringMultiWindowAnimation = true;
ObjectAnimator mwAnimation = ObjectAnimator.ofFloat(this, DEPTH,
ObjectAnimator mwAnimation = ObjectAnimator.ofFloat(this, STATE_DEPTH,
mLauncher.getStateManager().getState().getDepth(mLauncher, isInMultiWindowMode))
.setDuration(300);
mwAnimation.addListener(new AnimatorListenerAdapter() {

View File

@ -27,9 +27,11 @@ import static com.android.launcher3.LauncherState.NO_OFFSET;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE;
import static com.android.launcher3.config.FeatureFlags.ENABLE_WIDGET_PICKER_DEPTH;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_APP_LAUNCH_TAP;
import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition;
@ -44,6 +46,7 @@ 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.Executors.THREAD_POOL_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.quickstep.util.BaseDepthController.WIDGET_DEPTH;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
import android.animation.AnimatorSet;
@ -75,6 +78,7 @@ import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepAccessibilityDelegate;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
import com.android.launcher3.anim.AnimatorPlaybackController;
@ -591,6 +595,11 @@ public class QuickstepLauncher extends Launcher {
public void onWidgetsTransition(float progress) {
super.onWidgetsTransition(progress);
onTaskbarInAppDisplayProgressUpdate(progress, WIDGETS_PAGE_PROGRESS_INDEX);
if (ENABLE_WIDGET_PICKER_DEPTH.get() && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
WIDGET_DEPTH.set(getDepthController(),
Utilities.mapToRange(progress, 0f, 1f, 0f, getDeviceProfile().bottomSheetDepth,
EMPHASIZED));
}
}
private void onTaskbarInAppDisplayProgressUpdate(float progress, int flag) {

View File

@ -16,7 +16,6 @@
package com.android.launcher3.uioverrides.states;
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
import android.content.Context;
@ -26,7 +25,6 @@ import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Themes;
/**
@ -44,9 +42,9 @@ public class AllAppsState extends LauncherState {
@Override
public <DEVICE_PROFILE_CONTEXT extends Context & DeviceProfileListenable>
int getTransitionDuration(DEVICE_PROFILE_CONTEXT context, boolean isToState) {
return context.getDeviceProfile().isTablet
? 500
: isToState ? 600 : 300;
return isToState
? context.getDeviceProfile().allAppsOpenDuration
: context.getDeviceProfile().allAppsCloseDuration;
}
@Override
@ -83,15 +81,7 @@ public class AllAppsState extends LauncherState {
protected <DEVICE_PROFILE_CONTEXT extends Context & DeviceProfile.DeviceProfileListenable>
float getDepthUnchecked(DEVICE_PROFILE_CONTEXT context) {
if (context.getDeviceProfile().isTablet) {
// The goal is to set wallpaper to zoom at workspaceContentScale when in AllApps.
// When depth is 0, wallpaper zoom is set to maxWallpaperScale.
// When depth is 1, wallpaper zoom is set to 1.
// For depth to achieve zoom set to maxWallpaperScale * workspaceContentScale:
float maxWallpaperScale = context.getResources().getFloat(
com.android.internal.R.dimen.config_wallpaperMaxScale);
return Utilities.mapToRange(
maxWallpaperScale * context.getDeviceProfile().workspaceContentScale,
maxWallpaperScale, 1f, 0f, 1f, LINEAR);
return context.getDeviceProfile().bottomSheetDepth;
} else {
// The scrim fades in at approximately 50% of the swipe gesture.
// This means that the depth should be greater than 1, in order to fully zoom out.

View File

@ -36,7 +36,7 @@ import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.launcher3.anim.Interpolators.clampToProgress;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.launcher3.statehandlers.DepthController.STATE_DEPTH;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@ -367,7 +367,7 @@ public final class TaskViewUtils {
});
if (depthController != null) {
out.setFloat(depthController, DEPTH, BACKGROUND_APP.getDepth(baseActivity),
out.setFloat(depthController, STATE_DEPTH, BACKGROUND_APP.getDepth(baseActivity),
TOUCH_RESPONSE_INTERPOLATOR);
}
}

View File

@ -24,6 +24,7 @@ import android.view.SurfaceControl;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.systemui.shared.system.BlurUtils;
/**
@ -31,7 +32,7 @@ import com.android.systemui.shared.system.BlurUtils;
*/
public class BaseDepthController {
public static final FloatProperty<BaseDepthController> DEPTH =
private static final FloatProperty<BaseDepthController> DEPTH =
new FloatProperty<BaseDepthController>("depth") {
@Override
public void setValue(BaseDepthController depthController, float depth) {
@ -44,6 +45,19 @@ public class BaseDepthController {
}
};
private static final MultiPropertyFactory<BaseDepthController> DEPTH_PROPERTY_FACTORY =
new MultiPropertyFactory<>("depthProperty", DEPTH, Float::max);
private static final int DEPTH_INDEX_STATE_TRANSITION = 1;
private static final int DEPTH_INDEX_WIDGET = 2;
/** Property to set the depth for state transition. */
public static final FloatProperty<BaseDepthController> STATE_DEPTH =
DEPTH_PROPERTY_FACTORY.get(DEPTH_INDEX_STATE_TRANSITION);
/** Property to set the depth for widget picker. */
public static final FloatProperty<BaseDepthController> WIDGET_DEPTH =
DEPTH_PROPERTY_FACTORY.get(DEPTH_INDEX_WIDGET);
protected final Launcher mLauncher;
/**

View File

@ -43,7 +43,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN;
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
import static com.android.launcher3.statehandlers.DepthController.STATE_DEPTH;
import static com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE;
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
@ -4416,7 +4416,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
DepthController depthController = getDepthController();
if (depthController != null) {
ObjectAnimator depthAnimator = ObjectAnimator.ofFloat(depthController, DEPTH,
ObjectAnimator depthAnimator = ObjectAnimator.ofFloat(depthController, STATE_DEPTH,
BACKGROUND_APP.getDepth(mActivity));
anim.play(depthAnimator);
}

View File

@ -18,4 +18,11 @@
<!-- The duration of the PagedView page snap animation -->
<integer name="config_pageSnapAnimationDuration">550</integer>
<!-- The duration of the Widget picker opening and closing animation -->
<integer name="config_bottomSheetOpenDuration">500</integer>
<integer name="config_bottomSheetCloseDuration">500</integer>
<!-- The duration of the AllApps opening and closing animation -->
<integer name="config_allAppsOpenDuration">@integer/config_bottomSheetOpenDuration</integer>
<integer name="config_allAppsCloseDuration">@integer/config_bottomSheetCloseDuration</integer>
</resources>

View File

@ -193,4 +193,15 @@
<dimen name="swipe_back_window_scale_x_margin">10dp</dimen>
<dimen name="swipe_back_window_max_delta_y">160dp</dimen>
<dimen name="swipe_back_window_corner_radius">40dp</dimen>
<!-- The duration of the bottom sheet opening and closing animation -->
<integer name="config_bottomSheetOpenDuration">267</integer>
<integer name="config_bottomSheetCloseDuration">267</integer>
<!-- The duration of the AllApps opening and closing animation -->
<integer name="config_allAppsOpenDuration">600</integer>
<integer name="config_allAppsCloseDuration">300</integer>
<!-- The max scale for the wallpaper when it's zoomed in -->
<item name="config_wallpaperMaxScale" format="float" type="dimen">0</item>
</resources>

View File

@ -22,6 +22,7 @@ import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_LANDS
import static com.android.launcher3.InvariantDeviceProfile.INDEX_TWO_PANEL_PORTRAIT;
import static com.android.launcher3.Utilities.dpiFromPx;
import static com.android.launcher3.Utilities.pxFromSp;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ICON_OVERLAP_FACTOR;
import static com.android.launcher3.icons.GraphicsUtils.getShapePath;
import static com.android.launcher3.testing.shared.ResourceUtils.pxFromDp;
@ -181,11 +182,19 @@ public class DeviceProfile {
private final int hotseatQsbShadowHeight;
public int hotseatBorderSpace;
// Bottom sheets
public int bottomSheetTopPadding;
public int bottomSheetOpenDuration;
public int bottomSheetCloseDuration;
public float bottomSheetWorkspaceScale;
public float bottomSheetDepth;
// All apps
public Point allAppsBorderSpacePx;
public int allAppsShiftRange;
public int allAppsTopPadding;
public int bottomSheetTopPadding;
public int allAppsOpenDuration;
public int allAppsCloseDuration;
public int allAppsCellHeightPx;
public int allAppsCellWidthPx;
public int allAppsIconSizePx;
@ -316,6 +325,21 @@ public class DeviceProfile {
bottomSheetTopPadding = mInsets.top // statusbar height
+ res.getDimensionPixelSize(R.dimen.bottom_sheet_extra_top_padding)
+ (isTablet ? 0 : edgeMarginPx); // phones need edgeMarginPx additional padding
bottomSheetOpenDuration = res.getInteger(R.integer.config_bottomSheetOpenDuration);
bottomSheetCloseDuration = res.getInteger(R.integer.config_bottomSheetCloseDuration);
if (isTablet) {
bottomSheetWorkspaceScale = workspaceContentScale;
// The goal is to set wallpaper to zoom at workspaceContentScale when in AllApps.
// When depth is 0, wallpaper zoom is set to maxWallpaperScale.
// When depth is 1, wallpaper zoom is set to 1.
// For depth to achieve zoom set to maxWallpaperScale * workspaceContentScale:
float maxWallpaperScale = res.getFloat(R.dimen.config_wallpaperMaxScale);
bottomSheetDepth = Utilities.mapToRange(maxWallpaperScale * workspaceContentScale,
maxWallpaperScale, 1f, 0f, 1f, LINEAR);
} else {
bottomSheetWorkspaceScale = 1f;
bottomSheetDepth = 0f;
}
folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale);
folderContentPaddingLeftRight =
@ -474,6 +498,8 @@ public class DeviceProfile {
allAppsShiftRange =
res.getDimensionPixelSize(R.dimen.all_apps_starting_vertical_translate);
}
allAppsOpenDuration = res.getInteger(R.integer.config_allAppsOpenDuration);
allAppsCloseDuration = res.getInteger(R.integer.config_allAppsCloseDuration);
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
R.dimen.drag_flingToDeleteMinVelocity);
@ -1434,9 +1460,15 @@ public class DeviceProfile {
writer.println(prefix + pxToDpStr("folderTopPadding", folderContentPaddingTop));
writer.println(prefix + pxToDpStr("bottomSheetTopPadding", bottomSheetTopPadding));
writer.println(prefix + "\tbottomSheetOpenDuration: " + bottomSheetOpenDuration);
writer.println(prefix + "\tbottomSheetCloseDuration: " + bottomSheetCloseDuration);
writer.println(prefix + "\tbottomSheetWorkspaceScale: " + bottomSheetWorkspaceScale);
writer.println(prefix + "\tbottomSheetDepth: " + bottomSheetDepth);
writer.println(prefix + pxToDpStr("allAppsShiftRange", allAppsShiftRange));
writer.println(prefix + pxToDpStr("allAppsTopPadding", allAppsTopPadding));
writer.println(prefix + "\tallAppsOpenDuration: " + allAppsOpenDuration);
writer.println(prefix + "\tallAppsCloseDuration: " + allAppsCloseDuration);
writer.println(prefix + pxToDpStr("allAppsIconSizePx", allAppsIconSizePx));
writer.println(prefix + pxToDpStr("allAppsIconTextSizePx", allAppsIconTextSizePx));
writer.println(prefix + pxToDpStr("allAppsIconDrawablePaddingPx",

View File

@ -42,6 +42,7 @@ import static com.android.launcher3.LauncherState.NO_SCALE;
import static com.android.launcher3.LauncherState.SPRING_LOADED;
import static com.android.launcher3.Utilities.postAsyncCallback;
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.getSupportedActions;
import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import static com.android.launcher3.logging.StatsLogManager.EventEnum;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
@ -3234,13 +3235,11 @@ public class Launcher extends StatefulActivity<LauncherState>
* @param progress Transition progress from 0 to 1; where 0 => home and 1 => widgets.
*/
public void onWidgetsTransition(float progress) {
if (mDeviceProfile.isTablet) {
float scale =
Utilities.comp(Utilities.comp(mDeviceProfile.workspaceContentScale) * progress);
float scale = Utilities.mapToRange(progress, 0f, 1f, 1f,
mDeviceProfile.bottomSheetWorkspaceScale, EMPHASIZED);
WORKSPACE_WIDGET_SCALE.set(getWorkspace(), scale);
HOTSEAT_WIDGET_SCALE.set(getHotseat(), scale);
}
}
private static class NonConfigInstance {
public Configuration config;

View File

@ -42,7 +42,7 @@ import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.util.MultiAdditivePropertyFactory;
import com.android.launcher3.util.MultiPropertyFactory;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.views.ScrimView;
@ -141,9 +141,9 @@ public class AllAppsTransitionController
private ScrimView mScrimView;
private final MultiAdditivePropertyFactory<View>
mAppsViewTranslationYPropertyFactory = new MultiAdditivePropertyFactory<>(
"appsViewTranslationY", View.TRANSLATION_Y);
private final MultiPropertyFactory<View>
mAppsViewTranslationYPropertyFactory = new MultiPropertyFactory<>(
"appsViewTranslationY", View.TRANSLATION_Y, Float::sum);
private MultiValueAlpha mAppsViewAlpha;
private boolean mIsTablet;

View File

@ -293,6 +293,11 @@ public final class FeatureFlags {
"Enable option to log the keyboard latency for both atomic and controlled keyboard "
+ "animations on an EditText");
// Change of wallpaper depth in widget picker is disabled for tests as it causes flakiness on
// very slow cuttlefish devices.
public static final BooleanFlag ENABLE_WIDGET_PICKER_DEPTH = new DeviceFlag(
"ENABLE_WIDGET_PICKER_DEPTH", true, "Enable changing depth in widget picker.");
public static void initialize(Context context) {
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {

View File

@ -20,7 +20,6 @@ import android.util.ArrayMap;
import android.util.FloatProperty;
import android.util.Log;
import android.util.Property;
import android.view.View;
/**
* Allows to combine multiple values set by several sources.
@ -30,43 +29,55 @@ import android.view.View;
* time.
*
* This class behaves similarly to [MultiValueAlpha], but is meant to be more abstract and reusable.
* It sets the addition of all values.
* It aggregate all values using the provided [aggregator].
*
* @param <T> Type where to apply the property.
*/
public class MultiAdditivePropertyFactory<T extends View> {
public class MultiPropertyFactory<T> {
private static final boolean DEBUG = false;
private static final String TAG = "MultiAdditivePropertyFactory";
private static final String TAG = "MultiPropertyFactory";
private final String mName;
private final ArrayMap<Integer, MultiAdditiveProperty> mProperties =
new ArrayMap<>();
private final ArrayMap<Integer, MultiProperty> mProperties = new ArrayMap<>();
// This is an optimization for cases when set is called repeatedly with the same setterIndex.
private float mAggregationOfOthers = 0f;
private Integer mLastIndexSet = -1;
private final Property<View, Float> mProperty;
private final Property<T, Float> mProperty;
private final FloatBiFunction mAggregator;
public MultiAdditivePropertyFactory(String name, Property<View, Float> property) {
/**
* Represents a function that accepts two float and produces a float.
*/
public interface FloatBiFunction {
/**
* Applies this function to the given arguments.
*/
float apply(float a, float b);
}
public MultiPropertyFactory(String name, Property<T, Float> property,
FloatBiFunction aggregator) {
mName = name;
mProperty = property;
mAggregator = aggregator;
}
/** Returns the [MultiFloatProperty] associated with [inx], creating it if not present. */
public MultiAdditiveProperty get(Integer index) {
public MultiProperty get(Integer index) {
return mProperties.computeIfAbsent(index,
(k) -> new MultiAdditiveProperty(index, mName + "_" + index));
(k) -> new MultiProperty(index, mName + "_" + index));
}
/**
* Each [setValue] will be aggregated with the other properties values created by the
* corresponding factory.
*/
class MultiAdditiveProperty extends FloatProperty<T> {
class MultiProperty extends FloatProperty<T> {
private final int mInx;
private float mValue = 0f;
MultiAdditiveProperty(int inx, String name) {
MultiProperty(int inx, String name) {
super(name);
mInx = inx;
}
@ -77,12 +88,13 @@ public class MultiAdditivePropertyFactory<T extends View> {
mAggregationOfOthers = 0f;
mProperties.forEach((key, property) -> {
if (key != mInx) {
mAggregationOfOthers += property.mValue;
mAggregationOfOthers =
mAggregator.apply(mAggregationOfOthers, property.mValue);
}
});
mLastIndexSet = mInx;
}
float lastAggregatedValue = mAggregationOfOthers + newValue;
float lastAggregatedValue = mAggregator.apply(mAggregationOfOthers, newValue);
mValue = newValue;
apply(obj, lastAggregatedValue);
@ -94,13 +106,13 @@ public class MultiAdditivePropertyFactory<T extends View> {
}
@Override
public Float get(T view) {
public Float get(T object) {
// The scale of the view should match mLastAggregatedValue. Still, if it has been
// changed without using this property, it can differ. As this get method is usually
// used to set the starting point on an animation, this would result in some jumps
// when the view scale is different than the last aggregated value. To stay on the
// safe side, let's return the real view scale.
return mProperty.get(view);
return mProperty.get(object);
}
@Override
@ -109,7 +121,7 @@ public class MultiAdditivePropertyFactory<T extends View> {
}
}
protected void apply(View view, float value) {
mProperty.set(view, value);
protected void apply(T object, float value) {
mProperty.set(object, value);
}
}

View File

@ -15,6 +15,8 @@
*/
package com.android.launcher3.widget;
import static com.android.launcher3.anim.Interpolators.EMPHASIZED;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
@ -26,6 +28,7 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.view.WindowInsets;
import android.view.animation.Interpolator;
import android.widget.Toast;
import androidx.annotation.GuardedBy;
@ -246,6 +249,12 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
return true;
}
@Override
protected Interpolator getIdleInterpolator() {
return mActivityContext.getDeviceProfile().isTablet
? EMPHASIZED : super.getIdleInterpolator();
}
//
// Drag related handling methods that implement {@link DragSource} interface.
//

View File

@ -85,7 +85,6 @@ public class WidgetsFullSheet extends BaseWidgetSheet
implements ProviderChangedListener, OnActivePageChangedListener,
WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener {
private static final long DEFAULT_OPEN_DURATION = 267;
private static final long FADE_IN_DURATION = 150;
private static final long EDUCATION_TIP_DELAY_MS = 200;
private static final long EDUCATION_DIALOG_DELAY_MS = 500;
@ -582,7 +581,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet
mOpenCloseAnimator.setValues(
PropertyValuesHolder.ofFloat(TRANSLATION_SHIFT, TRANSLATION_SHIFT_OPENED));
mOpenCloseAnimator
.setDuration(DEFAULT_OPEN_DURATION)
.setDuration(mActivityContext.getDeviceProfile().bottomSheetOpenDuration)
.setInterpolator(AnimationUtils.loadInterpolator(
getContext(), android.R.interpolator.linear_out_slow_in));
mOpenCloseAnimator.addListener(new AnimatorListenerAdapter() {
@ -603,7 +602,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet
@Override
protected void handleClose(boolean animate) {
handleClose(animate, DEFAULT_OPEN_DURATION);
handleClose(animate, mActivityContext.getDeviceProfile().bottomSheetCloseDuration);
}
@Override

View File

@ -42,9 +42,9 @@ public class AllAppsState extends LauncherState {
@Override
public <DEVICE_PROFILE_CONTEXT extends Context & DeviceProfileListenable>
int getTransitionDuration(DEVICE_PROFILE_CONTEXT context, boolean isToState) {
return !context.getDeviceProfile().isTablet && isToState
? 600
: isToState ? 500 : 300;
return isToState
? context.getDeviceProfile().allAppsOpenDuration
: context.getDeviceProfile().allAppsCloseDuration;
}
@Override

View File

@ -16,25 +16,31 @@
package com.android.launcher3.util
import android.view.View
import android.util.FloatProperty
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat
import org.junit.Test
import org.junit.runner.RunWith
/** Unit tests for [MultiAdditivePropertyFactory] */
/** Unit tests for [MultiPropertyFactory] */
@SmallTest
@RunWith(AndroidJUnit4::class)
class MultiAdditivePropertyTest {
class MultiPropertyFactoryTest {
private val received = mutableListOf<Float>()
private val factory =
object : MultiAdditivePropertyFactory<View?>("Test", View.TRANSLATION_X) {
override fun apply(obj: View?, value: Float) {
private val receiveProperty: FloatProperty<Any> = object : FloatProperty<Any>("receive") {
override fun setValue(obj: Any?, value: Float) {
received.add(value)
}
override fun get(o: Any): Float {
return 0f
}
}
private val factory = MultiPropertyFactory("depth_property", receiveProperty) {
x: Float, y: Float -> x + y
}
private val p1 = factory.get(1)