Merging from ub-launcher3-rvc-qpr-dev @ build 6770831
Bug:150504032 Test: manual, presubmit on the source branch x20/teams/android-launcher/merge/ub-launcher3-rvc-qpr-dev_rvc-qpr-dev_6770831.html Change-Id: Ic07dd8bd495cd0e013a00a29d9d9f11e246dc568 Merged-In: I5e9c73a7ac3033fe82006c4bd72824f56b8988f8
This commit is contained in:
@@ -43,9 +43,11 @@ import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.MainThread;
|
||||
import androidx.annotation.WorkerThread;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.popup.RemoteActionShortcut;
|
||||
import com.android.launcher3.popup.SystemShortcut;
|
||||
@@ -57,6 +59,7 @@ import com.android.launcher3.util.SimpleBroadcastReceiver;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Data model for digital wellbeing status of apps.
|
||||
@@ -72,6 +75,9 @@ public final class WellbeingModel {
|
||||
private static final int MSG_FULL_REFRESH = 3;
|
||||
|
||||
// Welbeing contract
|
||||
private static final String PATH_ACTIONS = "actions";
|
||||
private static final String PATH_MINIMAL_DEVICE = "minimal_device";
|
||||
private static final String METHOD_GET_MINIMAL_DEVICE_CONFIG = "get_minimal_device_config";
|
||||
private static final String METHOD_GET_ACTIONS = "get_actions";
|
||||
private static final String EXTRA_ACTIONS = "actions";
|
||||
private static final String EXTRA_ACTION = "action";
|
||||
@@ -104,15 +110,22 @@ public final class WellbeingModel {
|
||||
mContentObserver = new ContentObserver(MAIN_EXECUTOR.getHandler()) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange, Uri uri) {
|
||||
// Wellbeing reports that app actions have changed.
|
||||
if (DEBUG || mIsInTest) {
|
||||
Log.d(TAG, "ContentObserver.onChange() called with: selfChange = [" + selfChange
|
||||
+ "], uri = [" + uri + "]");
|
||||
Log.d(TAG, "ContentObserver.onChange() called with: selfChange = ["
|
||||
+ selfChange + "], uri = [" + uri + "]");
|
||||
}
|
||||
Preconditions.assertUIThread();
|
||||
updateWellbeingData();
|
||||
|
||||
if (uri.getPath().contains(PATH_ACTIONS)) {
|
||||
// Wellbeing reports that app actions have changed.
|
||||
updateWellbeingData();
|
||||
} else if (uri.getPath().contains(PATH_MINIMAL_DEVICE)) {
|
||||
// Wellbeing reports that minimal device state or config is changed.
|
||||
updateLauncherModel();
|
||||
}
|
||||
}
|
||||
};
|
||||
FeatureFlags.ENABLE_MINIMAL_DEVICE.addChangeListener(mContext, this::updateLauncherModel);
|
||||
|
||||
if (!TextUtils.isEmpty(mWellbeingProviderPkg)) {
|
||||
context.registerReceiver(
|
||||
@@ -146,14 +159,18 @@ public final class WellbeingModel {
|
||||
private void restartObserver() {
|
||||
final ContentResolver resolver = mContext.getContentResolver();
|
||||
resolver.unregisterContentObserver(mContentObserver);
|
||||
Uri actionsUri = apiBuilder().path("actions").build();
|
||||
Uri actionsUri = apiBuilder().path(PATH_ACTIONS).build();
|
||||
Uri minimalDeviceUri = apiBuilder().path(PATH_MINIMAL_DEVICE).build();
|
||||
try {
|
||||
resolver.registerContentObserver(
|
||||
actionsUri, true /* notifyForDescendants */, mContentObserver);
|
||||
resolver.registerContentObserver(
|
||||
minimalDeviceUri, true /* notifyForDescendants */, mContentObserver);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to register content observer for " + actionsUri + ": " + e);
|
||||
if (mIsInTest) throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
updateWellbeingData();
|
||||
}
|
||||
|
||||
@@ -191,12 +208,42 @@ public final class WellbeingModel {
|
||||
mWorkerHandler.sendEmptyMessage(MSG_FULL_REFRESH);
|
||||
}
|
||||
|
||||
private void updateLauncherModel() {
|
||||
if (!FeatureFlags.ENABLE_MINIMAL_DEVICE.get()) return;
|
||||
|
||||
// TODO: init Launcher in minimal device / normal mode
|
||||
}
|
||||
|
||||
private Uri.Builder apiBuilder() {
|
||||
return new Uri.Builder()
|
||||
.scheme(SCHEME_CONTENT)
|
||||
.authority(mWellbeingProviderPkg + ".api");
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch most up-to-date minimal device config.
|
||||
*/
|
||||
@WorkerThread
|
||||
private void runWithMinimalDeviceConfigs(Consumer<Bundle> consumer) {
|
||||
if (DEBUG || mIsInTest) {
|
||||
Log.d(TAG, "runWithMinimalDeviceConfigs() called");
|
||||
}
|
||||
Preconditions.assertNonUiThread();
|
||||
|
||||
final Uri contentUri = apiBuilder().build();
|
||||
final Bundle remoteBundle;
|
||||
try (ContentProviderClient client = mContext.getContentResolver()
|
||||
.acquireUnstableContentProviderClient(contentUri)) {
|
||||
remoteBundle = client.call(
|
||||
METHOD_GET_MINIMAL_DEVICE_CONFIG, null /* args */, null /* extras */);
|
||||
consumer.accept(remoteBundle);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Failed to retrieve data from " + contentUri + ": " + e);
|
||||
if (mIsInTest) throw new RuntimeException(e);
|
||||
}
|
||||
if (DEBUG || mIsInTest) Log.i(TAG, "runWithMinimalDeviceConfigs(): finished");
|
||||
}
|
||||
|
||||
private boolean updateActions(String... packageNames) {
|
||||
if (packageNames.length == 0) {
|
||||
return true;
|
||||
|
||||
@@ -24,11 +24,13 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MO
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCRIM_FADE;
|
||||
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.PLAY_ATOMIC_OVERVIEW_PEEK;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
|
||||
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
|
||||
|
||||
import android.util.FloatProperty;
|
||||
|
||||
@@ -63,6 +65,7 @@ public abstract class BaseRecentsViewStateController<T extends RecentsView>
|
||||
float[] scaleAndOffset = state.getOverviewScaleAndOffset(mLauncher);
|
||||
RECENTS_SCALE_PROPERTY.set(mRecentsView, scaleAndOffset[0]);
|
||||
ADJACENT_PAGE_OFFSET.set(mRecentsView, scaleAndOffset[1]);
|
||||
TASK_SECONDARY_TRANSLATION.set(mRecentsView, 0f);
|
||||
|
||||
getContentAlphaProperty().set(mRecentsView, state.overviewUi ? 1f : 0);
|
||||
OverviewScrim scrim = mLauncher.getDragLayer().getOverviewScrim();
|
||||
@@ -97,6 +100,8 @@ public abstract class BaseRecentsViewStateController<T extends RecentsView>
|
||||
config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR));
|
||||
setter.setFloat(mRecentsView, ADJACENT_PAGE_OFFSET, scaleAndOffset[1],
|
||||
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR));
|
||||
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
|
||||
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
|
||||
|
||||
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
|
||||
config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.launcher3.uioverrides.states;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_2;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
@@ -92,7 +93,8 @@ public class AllAppsState extends LauncherState {
|
||||
|
||||
@Override
|
||||
public float[] getOverviewScaleAndOffset(Launcher launcher) {
|
||||
return new float[] {0.9f, 0};
|
||||
float offset = ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(launcher) ? 1 : 0;
|
||||
return new float[] {0.9f, offset};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
@@ -142,6 +142,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
|
||||
Log.d(TestProtocol.OVERIEW_NOT_ALLAPPS,
|
||||
"PortraitStatesTouchController.getTargetState 1");
|
||||
}
|
||||
if (ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(mLauncher)) {
|
||||
// Don't allow swiping down to overview.
|
||||
return NORMAL;
|
||||
}
|
||||
return TouchInteractionService.isConnected() ?
|
||||
mLauncher.getStateManager().getLastState() : NORMAL;
|
||||
} else if (fromState == OVERVIEW) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_REC
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
|
||||
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.annotation.TargetApi;
|
||||
@@ -52,6 +53,7 @@ import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.util.WindowBounds;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.util.ShelfPeekAnim;
|
||||
import com.android.quickstep.util.SplitScreenBounds;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
@@ -106,7 +108,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
public abstract void onAssistantVisibilityChanged(float visibility);
|
||||
|
||||
public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
|
||||
boolean activityVisible, Consumer<AnimatorPlaybackController> callback);
|
||||
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback);
|
||||
|
||||
public abstract ActivityInitListener createActivityInitListener(
|
||||
Predicate<Boolean> onInitListener);
|
||||
@@ -319,11 +321,11 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
|
||||
protected final ACTIVITY_TYPE mActivity;
|
||||
private final STATE_TYPE mStartState;
|
||||
private final Consumer<AnimatorPlaybackController> mCallback;
|
||||
private final Consumer<AnimatorControllerWithResistance> mCallback;
|
||||
|
||||
private boolean mIsAttachedToWindow;
|
||||
|
||||
DefaultAnimationFactory(Consumer<AnimatorPlaybackController> callback) {
|
||||
DefaultAnimationFactory(Consumer<AnimatorControllerWithResistance> callback) {
|
||||
mCallback = callback;
|
||||
|
||||
mActivity = getCreatedActivity();
|
||||
@@ -351,7 +353,14 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
controller.setEndAction(() -> mActivity.getStateManager().goToState(
|
||||
controller.getInterpolatedProgress() > 0.5 ? mOverviewState : mBackgroundState,
|
||||
false));
|
||||
mCallback.accept(controller);
|
||||
|
||||
RecentsView recentsView = mActivity.getOverviewPanel();
|
||||
AnimatorControllerWithResistance controllerWithResistance =
|
||||
AnimatorControllerWithResistance.createForRecents(controller, mActivity,
|
||||
recentsView.getPagedViewOrientedState(), mActivity.getDeviceProfile(),
|
||||
recentsView, RECENTS_SCALE_PROPERTY, recentsView,
|
||||
TASK_SECONDARY_TRANSLATION);
|
||||
mCallback.accept(controllerWithResistance);
|
||||
|
||||
// Creating the activity controller animation sometimes reapplies the launcher state
|
||||
// (because we set the animation as the current state animation), so we reapply the
|
||||
|
||||
+1
-2
@@ -184,8 +184,7 @@ abstract class SwipeUpGestureTutorialController extends TutorialController {
|
||||
|
||||
@Override
|
||||
public void updateFinalShift() {
|
||||
float progress = mCurrentShift.value / mDragLengthFactor;
|
||||
mWindowTransitionController.setPlayFraction(progress);
|
||||
mWindowTransitionController.setProgress(mCurrentShift.value, mDragLengthFactor);
|
||||
mTaskViewSimulator.apply(mTransformParams);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2020 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
|
||||
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
|
||||
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
|
||||
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.FloatProperty;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.quickstep.LauncherActivityInterface;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
/**
|
||||
* Controls an animation that can go beyond progress = 1, at which point resistance should be
|
||||
* applied. Internally, this is a wrapper around 2 {@link AnimatorPlaybackController}s, one that
|
||||
* runs from progress 0 to 1 like normal, then one that seamlessly continues that animation but
|
||||
* starts applying resistance as well.
|
||||
*/
|
||||
public class AnimatorControllerWithResistance {
|
||||
|
||||
/**
|
||||
* How much farther we can drag past overview in 2-button mode, as a factor of the distance
|
||||
* it takes to drag from an app to overview.
|
||||
*/
|
||||
public static final float TWO_BUTTON_EXTRA_DRAG_FACTOR = 0.25f;
|
||||
|
||||
private enum RecentsParams {
|
||||
FROM_APP(0.75f, 0.5f, 1f),
|
||||
FROM_OVERVIEW(1f, 0.75f, 0.5f);
|
||||
|
||||
RecentsParams(float scaleStartResist, float scaleMaxResist, float translationFactor) {
|
||||
this.scaleStartResist = scaleStartResist;
|
||||
this.scaleMaxResist = scaleMaxResist;
|
||||
this.translationFactor = translationFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start slowing down the rate of scaling down when recents view is smaller than this scale.
|
||||
*/
|
||||
public final float scaleStartResist;
|
||||
|
||||
/**
|
||||
* Recents view will reach this scale at the very end of the drag.
|
||||
*/
|
||||
public final float scaleMaxResist;
|
||||
|
||||
/**
|
||||
* How much translation to apply to RecentsView when the drag reaches the top of the screen,
|
||||
* where 0 will keep it centered and 1 will have it barely touch the top of the screen.
|
||||
*/
|
||||
public final float translationFactor;
|
||||
}
|
||||
|
||||
private static final TimeInterpolator RECENTS_SCALE_RESIST_INTERPOLATOR = DEACCEL;
|
||||
private static final TimeInterpolator RECENTS_TRANSLATE_RESIST_INTERPOLATOR = LINEAR;
|
||||
|
||||
private final AnimatorPlaybackController mNormalController;
|
||||
private final AnimatorPlaybackController mResistanceController;
|
||||
|
||||
// Initialize to -1 so the first 0 gets applied.
|
||||
private float mLastNormalProgress = -1;
|
||||
private float mLastResistProgress;
|
||||
|
||||
public AnimatorControllerWithResistance(AnimatorPlaybackController normalController,
|
||||
AnimatorPlaybackController resistanceController) {
|
||||
mNormalController = normalController;
|
||||
mResistanceController = resistanceController;
|
||||
}
|
||||
|
||||
public AnimatorPlaybackController getNormalController() {
|
||||
return mNormalController;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the current progress of the animation.
|
||||
* @param progress From 0 to maxProgress, where 1 is the target we are animating towards.
|
||||
* @param maxProgress > 1, this is where the resistance will be applied.
|
||||
*/
|
||||
public void setProgress(float progress, float maxProgress) {
|
||||
float normalProgress = Utilities.boundToRange(progress, 0, 1);
|
||||
if (normalProgress != mLastNormalProgress) {
|
||||
mLastNormalProgress = normalProgress;
|
||||
mNormalController.setPlayFraction(normalProgress);
|
||||
}
|
||||
if (maxProgress <= 1) {
|
||||
return;
|
||||
}
|
||||
float resistProgress = progress <= 1 ? 0 : Utilities.getProgress(progress, 1, maxProgress);
|
||||
if (resistProgress != mLastResistProgress) {
|
||||
mLastResistProgress = resistProgress;
|
||||
mResistanceController.setPlayFraction(resistProgress);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies resistance to recents when swiping up past its target position.
|
||||
* @param normalController The controller to run from 0 to 1 before this resistance applies.
|
||||
* @param context Used to compute start and end values.
|
||||
* @param recentsOrientedState Used to compute start and end values.
|
||||
* @param dp Used to compute start and end values.
|
||||
* @param scaleTarget The target for the scaleProperty.
|
||||
* @param scaleProperty Animate the value to change the scale of the window/recents view.
|
||||
* @param translationTarget The target for the translationProperty.
|
||||
* @param translationProperty Animate the value to change the translation of the recents view.
|
||||
*/
|
||||
public static <SCALE, TRANSLATION> AnimatorControllerWithResistance createForRecents(
|
||||
AnimatorPlaybackController normalController, Context context,
|
||||
RecentsOrientedState recentsOrientedState, DeviceProfile dp, SCALE scaleTarget,
|
||||
FloatProperty<SCALE> scaleProperty, TRANSLATION translationTarget,
|
||||
FloatProperty<TRANSLATION> translationProperty) {
|
||||
|
||||
PendingAnimation resistAnim = createRecentsResistanceAnim(null, context,
|
||||
recentsOrientedState, dp, scaleTarget, scaleProperty, translationTarget,
|
||||
translationProperty, RecentsParams.FROM_APP);
|
||||
|
||||
AnimatorPlaybackController resistanceController = resistAnim.createPlaybackController();
|
||||
return new AnimatorControllerWithResistance(normalController, resistanceController);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the resistance animation for {@link #createForRecents}, or can be used separately
|
||||
* when starting from recents, i.e. {@link #createRecentsResistanceFromOverviewAnim}.
|
||||
*/
|
||||
public static <SCALE, TRANSLATION> PendingAnimation createRecentsResistanceAnim(
|
||||
@Nullable PendingAnimation resistAnim, Context context,
|
||||
RecentsOrientedState recentsOrientedState, DeviceProfile dp, SCALE scaleTarget,
|
||||
FloatProperty<SCALE> scaleProperty, TRANSLATION translationTarget,
|
||||
FloatProperty<TRANSLATION> translationProperty, RecentsParams params) {
|
||||
Rect startRect = new Rect();
|
||||
LauncherActivityInterface.INSTANCE.calculateTaskSize(context, dp, startRect,
|
||||
recentsOrientedState.getOrientationHandler());
|
||||
long distanceToCover = startRect.bottom;
|
||||
boolean isTwoButtonMode = SysUINavigationMode.getMode(context) == TWO_BUTTONS;
|
||||
if (isTwoButtonMode) {
|
||||
// We can only drag a small distance past overview, not to the top of the screen.
|
||||
distanceToCover = (long)
|
||||
((dp.heightPx - startRect.bottom) * TWO_BUTTON_EXTRA_DRAG_FACTOR);
|
||||
}
|
||||
if (resistAnim == null) {
|
||||
resistAnim = new PendingAnimation(distanceToCover * 2);
|
||||
}
|
||||
|
||||
PointF pivot = new PointF();
|
||||
float fullscreenScale = recentsOrientedState.getFullScreenScaleAndPivot(
|
||||
startRect, dp, pivot);
|
||||
float startScale = 1;
|
||||
float prevScaleRate = (fullscreenScale - startScale) / (dp.heightPx - startRect.bottom);
|
||||
// This is what the scale would be at the end of the drag if we didn't apply resistance.
|
||||
float endScale = startScale - prevScaleRate * distanceToCover;
|
||||
final TimeInterpolator scaleInterpolator;
|
||||
if (isTwoButtonMode) {
|
||||
// We are bounded by the distance of the drag, so we don't need to apply resistance.
|
||||
scaleInterpolator = LINEAR;
|
||||
} else {
|
||||
// Create an interpolator that resists the scale so the scale doesn't get smaller than
|
||||
// RECENTS_SCALE_MAX_RESIST.
|
||||
float startResist = Utilities.getProgress(params.scaleStartResist , startScale,
|
||||
endScale);
|
||||
float maxResist = Utilities.getProgress(params.scaleMaxResist, startScale, endScale);
|
||||
scaleInterpolator = t -> {
|
||||
if (t < startResist) {
|
||||
return t;
|
||||
}
|
||||
float resistProgress = Utilities.getProgress(t, startResist, 1);
|
||||
resistProgress = RECENTS_SCALE_RESIST_INTERPOLATOR.getInterpolation(resistProgress);
|
||||
return startResist + resistProgress * (maxResist - startResist);
|
||||
};
|
||||
}
|
||||
resistAnim.addFloat(scaleTarget, scaleProperty, startScale, endScale,
|
||||
scaleInterpolator);
|
||||
|
||||
if (!isTwoButtonMode) {
|
||||
// Compute where the task view would be based on the end scale, if we didn't translate.
|
||||
RectF endRectF = new RectF(startRect);
|
||||
Matrix temp = new Matrix();
|
||||
temp.setScale(params.scaleMaxResist, params.scaleMaxResist, pivot.x, pivot.y);
|
||||
temp.mapRect(endRectF);
|
||||
// Translate such that the task view touches the top of the screen when drag does.
|
||||
float endTranslation = endRectF.top * recentsOrientedState.getOrientationHandler()
|
||||
.getSecondaryTranslationDirectionFactor() * params.translationFactor;
|
||||
resistAnim.addFloat(translationTarget, translationProperty, 0, endTranslation,
|
||||
RECENTS_TRANSLATE_RESIST_INTERPOLATOR);
|
||||
}
|
||||
|
||||
return resistAnim;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to update or create a PendingAnimation suitable for animating
|
||||
* a RecentsView interaction that started from the overview state.
|
||||
*/
|
||||
public static PendingAnimation createRecentsResistanceFromOverviewAnim(
|
||||
BaseDraggingActivity activity, @Nullable PendingAnimation resistanceAnim) {
|
||||
RecentsView recentsView = activity.getOverviewPanel();
|
||||
return createRecentsResistanceAnim(resistanceAnim, activity,
|
||||
recentsView.getPagedViewOrientedState(), activity.getDeviceProfile(),
|
||||
recentsView, RECENTS_SCALE_PROPERTY, recentsView, TASK_SECONDARY_TRANSLATION,
|
||||
RecentsParams.FROM_OVERVIEW);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user