Merge "Reusing the existing handler when quickscrub starts" into ub-launcher3-master
diff --git a/quickstep/libs/sysui_shared.jar b/quickstep/libs/sysui_shared.jar
index 18ddeee..85b40d0 100644
--- a/quickstep/libs/sysui_shared.jar
+++ b/quickstep/libs/sysui_shared.jar
Binary files differ
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 40436d1..9cc7973 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -34,6 +34,9 @@
<!-- TODO: This can be calculated using other resource values -->
<dimen name="all_apps_search_box_full_height">90dp</dimen>
- <dimen name="drag_layer_trans_y">25dp</dimen>
+ <!-- Launcher app transition -->
+ <dimen name="content_trans_y">25dp</dimen>
+ <dimen name="workspace_trans_y">80dp</dimen>
+ <dimen name="shelf_min_value">-2.857dp</dimen>
</resources>
diff --git a/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
new file mode 100644
index 0000000..489e55b
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/LauncherAnimationRunner.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3;
+
+import android.animation.AnimatorSet;
+import android.os.Handler;
+
+import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
+
+import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
+
+public abstract class LauncherAnimationRunner implements RemoteAnimationRunnerCompat {
+
+ AnimatorSet mAnimator;
+ private Launcher mLauncher;
+
+ LauncherAnimationRunner(Launcher launcher) {
+ mLauncher = launcher;
+ }
+
+ @Override
+ public void onAnimationCancelled() {
+ postAtFrontOfQueueAsynchronously(mLauncher.getWindow().getDecorView().getHandler(), () -> {
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManager.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManager.java
index dd05cfe..256e926 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManager.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import static com.android.launcher3.views.AllAppsScrim.SCRIM_PROGRESS;
import static com.android.systemui.shared.recents.utilities.Utilities.getNextFrameNumber;
import static com.android.systemui.shared.recents.utilities.Utilities.getSurface;
import static com.android.systemui.shared.recents.utilities.Utilities.postAtFrontOfQueueAsynchronously;
@@ -25,10 +26,13 @@
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
@@ -38,48 +42,67 @@
import com.android.launcher3.InsettableFrameLayout.LayoutParams;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.views.AllAppsScrim;
+import com.android.systemui.shared.system.ActivityCompat;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
+import com.android.systemui.shared.system.RemoteAnimationDefinitionCompat;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
+import com.android.systemui.shared.system.WindowManagerWrapper;
/**
- * Manages the opening app animations from Launcher.
+ * Manages the opening and closing app transitions from Launcher.
*/
public class LauncherAppTransitionManager {
+ private static final String TAG = "LauncherTransition";
private static final int REFRESH_RATE_MS = 16;
+ private static final int CLOSING_TRANSITION_DURATION_MS = 350;
+
private final DragLayer mDragLayer;
private final Launcher mLauncher;
private final DeviceProfile mDeviceProfile;
- private final float mDragLayerTransY;
+ private final float mContentTransY;
+ private final float mWorkspaceTransY;
+ // The smallest y-value the shelf will reach on screen, before overshooting back down to 0.
+ private final float mShelfMinValue;
private ImageView mFloatingView;
+ private boolean mIsRtl;
public LauncherAppTransitionManager(Launcher launcher) {
mLauncher = launcher;
mDragLayer = launcher.getDragLayer();
mDeviceProfile = launcher.getDeviceProfile();
- mDragLayerTransY =
- launcher.getResources().getDimensionPixelSize(R.dimen.drag_layer_trans_y);
+ mIsRtl = Utilities.isRtl(launcher.getResources());
+
+ Resources res = launcher.getResources();
+ mContentTransY = res.getDimensionPixelSize(R.dimen.content_trans_y);
+ mWorkspaceTransY = res.getDimensionPixelSize(R.dimen.workspace_trans_y);
+ mShelfMinValue = res.getDimensionPixelSize(R.dimen.shelf_min_value);
}
+ /**
+ * @return A Bundle with remote animations that controls how the window of the opening
+ * targets are displayed.
+ */
public Bundle getActivityLauncherOptions(View v) {
- RemoteAnimationRunnerCompat runner = new RemoteAnimationRunnerCompat() {
+ RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mLauncher) {
@Override
public void onAnimationStart(RemoteAnimationTargetCompat[] targets,
Runnable finishedCallback) {
// Post at front of queue ignoring sync barriers to make sure it gets processed
// before the next frame.
postAtFrontOfQueueAsynchronously(v.getHandler(), () -> {
- AnimatorSet both = new AnimatorSet();
- both.play(getLauncherAnimators(v));
- both.play(getAppWindowAnimators(v, targets));
- both.addListener(new AnimatorListenerAdapter() {
+ mAnimator = new AnimatorSet();
+ mAnimator.play(getLauncherAnimators(v));
+ mAnimator.play(getWindowAnimators(v, targets));
+ mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Reset launcher to normal state
@@ -96,51 +119,62 @@
finishedCallback.run();
}
});
- both.start();
+ mAnimator.start();
// Because t=0 has the app icon in its original spot, we can skip the first
// frame and have the same movement one frame earlier.
- both.setCurrentPlayTime(REFRESH_RATE_MS);
+ mAnimator.setCurrentPlayTime(REFRESH_RATE_MS);
});
}
-
- @Override
- public void onAnimationCancelled() {
- }
};
return ActivityOptionsCompat.makeRemoteAnimation(
new RemoteAnimationAdapterCompat(runner, 500, 380)).toBundle();
}
+ /**
+ * @return Animators that control the movements of the Launcher and icon of the opening target.
+ */
private AnimatorSet getLauncherAnimators(View v) {
AnimatorSet launcherAnimators = new AnimatorSet();
- launcherAnimators.play(getHideLauncherAnimator());
- launcherAnimators.play(getAppIconAnimator(v));
+ launcherAnimators.play(getLauncherContentAnimator(false /* show */));
+ launcherAnimators.play(getIconAnimator(v));
return launcherAnimators;
}
- private AnimatorSet getHideLauncherAnimator() {
+ /**
+ * Content is everything on screen except the background and the floating view (if any).
+ *
+ * @param show If true: Animate the content so that it moves upwards and fades in.
+ * Else: Animate the content so that it moves downwards and fades out.
+ */
+ private AnimatorSet getLauncherContentAnimator(boolean show) {
AnimatorSet hideLauncher = new AnimatorSet();
- // Animate the background content so that it moves downwards and fades out.
- if (mLauncher.isInState(LauncherState.ALL_APPS)) {
+ float[] alphas = show
+ ? new float[] {0, 1}
+ : new float[] {1, 0};
+ float[] trans = show
+ ? new float[] {mContentTransY, 0,}
+ : new float[] {0, mContentTransY};
+
+ if (mLauncher.isInState(LauncherState.ALL_APPS) && !mDeviceProfile.isVerticalBarLayout()) {
+ // All Apps in portrait mode is full screen, so we only animate AllAppsContainerView.
View appsView = mLauncher.getAppsView();
- ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, 1f, 0f);
+ ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas);
alpha.setDuration(217);
alpha.setInterpolator(Interpolators.LINEAR);
- ObjectAnimator transY = ObjectAnimator.ofFloat(appsView, View.TRANSLATION_Y, 0,
- mDragLayerTransY);
+ ObjectAnimator transY = ObjectAnimator.ofFloat(appsView, View.TRANSLATION_Y, trans);
transY.setInterpolator(Interpolators.AGGRESSIVE_EASE);
transY.setDuration(350);
hideLauncher.play(alpha);
hideLauncher.play(transY);
} else {
- ObjectAnimator dragLayerAlpha = ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, 1f, 0f);
+ ObjectAnimator dragLayerAlpha = ObjectAnimator.ofFloat(mDragLayer, View.ALPHA, alphas);
dragLayerAlpha.setDuration(217);
dragLayerAlpha.setInterpolator(Interpolators.LINEAR);
ObjectAnimator dragLayerTransY = ObjectAnimator.ofFloat(mDragLayer, View.TRANSLATION_Y,
- 0, mDragLayerTransY);
+ trans);
dragLayerTransY.setInterpolator(Interpolators.AGGRESSIVE_EASE);
dragLayerTransY.setDuration(350);
@@ -150,22 +184,32 @@
return hideLauncher;
}
- private AnimatorSet getAppIconAnimator(View v) {
- // Create a copy of the app icon
+ /**
+ * @return Animator that controls the icon used to launch the target.
+ */
+ private AnimatorSet getIconAnimator(View v) {
+ boolean isBubbleTextView = v instanceof BubbleTextView;
mFloatingView = new ImageView(mLauncher);
- Bitmap iconBitmap = ((FastBitmapDrawable) ((BubbleTextView) v).getIcon()).getBitmap();
- mFloatingView.setImageDrawable(new FastBitmapDrawable(iconBitmap));
+ if (isBubbleTextView) {
+ // Create a copy of the app icon
+ Bitmap iconBitmap = ((FastBitmapDrawable) ((BubbleTextView) v).getIcon()).getBitmap();
+ mFloatingView.setImageDrawable(new FastBitmapDrawable(iconBitmap));
+ }
- // Position the copy of the app icon exactly on top of the original
+ // Position the floating view exactly on top of the original
Rect rect = new Rect();
mDragLayer.getDescendantRectRelativeToSelf(v, rect);
- int viewLocationLeft = rect.left;
+ int viewLocationStart = mIsRtl
+ ? mDeviceProfile.widthPx - rect.right
+ : rect.left;
int viewLocationTop = rect.top;
- ((BubbleTextView) v).getIconBounds(rect);
+ if (isBubbleTextView) {
+ ((BubbleTextView) v).getIconBounds(rect);
+ }
LayoutParams lp = new LayoutParams(rect.width(), rect.height());
lp.ignoreInsets = true;
- lp.leftMargin = viewLocationLeft + rect.left;
+ lp.setMarginStart(viewLocationStart + rect.left);
lp.topMargin = viewLocationTop + rect.top;
mFloatingView.setLayoutParams(lp);
@@ -177,8 +221,13 @@
// Animate the app icon to the center
float centerX = mDeviceProfile.widthPx / 2;
float centerY = mDeviceProfile.heightPx / 2;
- float dX = centerX - lp.leftMargin - (lp.width / 2);
+
+ float xPosition = mIsRtl
+ ? mDeviceProfile.widthPx - lp.getMarginStart() - rect.width()
+ : lp.getMarginStart();
+ float dX = centerX - xPosition - (lp.width / 2);
float dY = centerY - lp.topMargin - (lp.height / 2);
+
ObjectAnimator x = ObjectAnimator.ofFloat(mFloatingView, View.TRANSLATION_X, 0f, dX);
ObjectAnimator y = ObjectAnimator.ofFloat(mFloatingView, View.TRANSLATION_Y, 0f, dY);
@@ -213,9 +262,16 @@
return appIconAnimatorSet;
}
- private ValueAnimator getAppWindowAnimators(View v, RemoteAnimationTargetCompat[] targets) {
- Rect iconBounds = new Rect();
- ((BubbleTextView) v).getIconBounds(iconBounds);
+ /**
+ * @return Animator that controls the window of the opening targets.
+ */
+ private ValueAnimator getWindowAnimators(View v, RemoteAnimationTargetCompat[] targets) {
+ Rect bounds = new Rect();
+ if (v instanceof BubbleTextView) {
+ ((BubbleTextView) v).getIconBounds(bounds);
+ } else {
+ mDragLayer.getDescendantRectRelativeToSelf(v, bounds);
+ }
int[] floatingViewBounds = new int[2];
Rect crop = new Rect();
@@ -228,12 +284,19 @@
@Override
public void onAnimationUpdate(ValueAnimator animation) {
+ final Surface surface = getSurface(mFloatingView);
+ final long frameNumber = surface != null ? getNextFrameNumber(surface) : -1;
+ if (frameNumber == -1) {
+ // Booo, not cool! Our surface got destroyed, so no reason to animate anything.
+ Log.w(TAG, "Failed to animate, surface got destroyed.");
+ return;
+ }
final float percent = animation.getAnimatedFraction();
final float easePercent = Interpolators.AGGRESSIVE_EASE.getInterpolation(percent);
// Calculate app icon size.
- float iconWidth = iconBounds.width() * mFloatingView.getScaleX();
- float iconHeight = iconBounds.height() * mFloatingView.getScaleY();
+ float iconWidth = bounds.width() * mFloatingView.getScaleX();
+ float iconHeight = bounds.height() * mFloatingView.getScaleY();
// Scale the app window to match the icon size.
float scaleX = iconWidth / mDeviceProfile.widthPx;
@@ -257,7 +320,7 @@
// Fade in the app window.
float alphaDelay = 0;
float alphaDuration = 50;
- float alpha = getValue(1f, 0f, alphaDelay, alphaDuration,
+ float alpha = getValue(0f, 1f, alphaDelay, alphaDuration,
appAnimator.getDuration() * percent, Interpolators.AGGRESSIVE_EASE);
// Animate the window crop so that it starts off as a square, and then reveals
@@ -273,9 +336,12 @@
for (RemoteAnimationTargetCompat target : targets) {
if (target.mode == RemoteAnimationTargetCompat.MODE_OPENING) {
t.setAlpha(target.leash, alpha);
+
+ // TODO: This isn't correct at the beginning of the animation, but better
+ // than nothing.
+ matrix.postTranslate(target.position.x, target.position.y);
t.setMatrix(target.leash, matrix);
t.setWindowCrop(target.leash, crop);
- Surface surface = getSurface(mFloatingView);
t.deferTransactionUntil(target.leash, surface, getNextFrameNumber(surface));
}
if (isFirstFrame) {
@@ -287,19 +353,168 @@
matrix.reset();
isFirstFrame = false;
}
-
- /**
- * Helper method that allows us to get interpolated values for embedded
- * animations with a delay and/or different duration.
- */
- private float getValue(float start, float end, float delay, float duration,
- float currentPlayTime, Interpolator i) {
- float time = Math.max(0, currentPlayTime - delay);
- float newPercent = Math.min(1f, time / duration);
- newPercent = i.getInterpolation(newPercent);
- return start * newPercent + end * (1 - newPercent);
- }
});
return appAnimator;
}
+
+ /**
+ * Registers remote animations used when closing apps to home screen.
+ */
+ public void registerRemoteAnimations() {
+ RemoteAnimationDefinitionCompat definition = new RemoteAnimationDefinitionCompat();
+ definition.addRemoteAnimation(WindowManagerWrapper.TRANSIT_WALLPAPER_OPEN,
+ new RemoteAnimationAdapterCompat(getWallpaperOpenRunner(), 0,
+ CLOSING_TRANSITION_DURATION_MS));
+
+// TODO: App controlled transition for unlock to home TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER
+
+ new ActivityCompat(mLauncher).registerRemoteAnimations(definition);
+ }
+
+ /**
+ * @return Runner that plays when user goes to Launcher
+ * ie. pressing home, swiping up from nav bar.
+ */
+ private RemoteAnimationRunnerCompat getWallpaperOpenRunner() {
+ return new LauncherAnimationRunner(mLauncher) {
+ @Override
+ public void onAnimationStart(RemoteAnimationTargetCompat[] targets,
+ Runnable finishedCallback) {
+ Handler handler = mLauncher.getWindow().getDecorView().getHandler();
+ postAtFrontOfQueueAsynchronously(handler, () -> {
+ // We use a separate transition for Overview mode.
+ if (mLauncher.isInState(LauncherState.OVERVIEW)) {
+ finishedCallback.run();
+ return;
+ }
+
+ mAnimator = new AnimatorSet();
+ mAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ finishedCallback.run();
+ }
+ });
+ mAnimator.play(getClosingWindowAnimators(targets));
+ mAnimator.play(getLauncherResumeAnimation());
+ mAnimator.start();
+ });
+ }
+ };
+ }
+
+ /**
+ * Animator that controls the transformations of the windows the targets that are closing.
+ */
+ private Animator getClosingWindowAnimators(RemoteAnimationTargetCompat[] targets) {
+ Matrix matrix = new Matrix();
+ float height = mLauncher.getDeviceProfile().heightPx;
+ float width = mLauncher.getDeviceProfile().widthPx;
+ float endX = Utilities.isRtl(mLauncher.getResources()) ? -width : width;
+
+ ValueAnimator closingAnimator = ValueAnimator.ofFloat(0, 1);
+ closingAnimator.setDuration(CLOSING_TRANSITION_DURATION_MS);
+
+ closingAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ boolean isFirstFrame = true;
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ final float percent = animation.getAnimatedFraction();
+ float currentPlayTime = percent * closingAnimator.getDuration();
+
+ float scale = getValue(1f, 0.8f, 0, 267, currentPlayTime,
+ Interpolators.AGGRESSIVE_EASE);
+ matrix.setScale(scale, scale);
+
+ float dX = getValue(0, endX, 0, 350, currentPlayTime,
+ Interpolators.AGGRESSIVE_EASE_IN_OUT);
+
+ TransactionCompat t = new TransactionCompat();
+ for (RemoteAnimationTargetCompat app : targets) {
+ if (app.mode == RemoteAnimationTargetCompat.MODE_CLOSING) {
+ t.setAlpha(app.leash, 1f - percent);
+
+ float dY = (height - (app.clipRect.height() * scale)) / 2f;
+ matrix.postTranslate(dX, dY);
+ t.setMatrix(app.leash, matrix);
+ }
+ // TODO: Layer should be set only once, but there is possibly a race condition
+ // where WindowManager is also calling setLayer.
+ int layer = app.mode == RemoteAnimationTargetCompat.MODE_CLOSING
+ ? Integer.MAX_VALUE
+ : app.prefixOrderIndex;
+ t.setLayer(app.leash, layer);
+ if (isFirstFrame) {
+ t.show(app.leash);
+ }
+ }
+ t.apply();
+
+ matrix.reset();
+ isFirstFrame = false;
+ }
+ });
+ return closingAnimator;
+ }
+
+ /**
+ * @return Animator that modifies Launcher as a result from {@link #getWallpaperOpenRunner}.
+ */
+ private AnimatorSet getLauncherResumeAnimation() {
+ if (mLauncher.isInState(LauncherState.ALL_APPS)
+ || mLauncher.getDeviceProfile().isVerticalBarLayout()) {
+ return getLauncherContentAnimator(true /* show */);
+ } else {
+ AnimatorSet workspaceAnimator = new AnimatorSet();
+ mLauncher.getWorkspace().setTranslationY(mWorkspaceTransY);
+ mLauncher.getWorkspace().setAlpha(0f);
+ workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(),
+ View.TRANSLATION_Y, mWorkspaceTransY, 0));
+ workspaceAnimator.play(ObjectAnimator.ofFloat(mLauncher.getWorkspace(), View.ALPHA,
+ 0, 1f));
+ workspaceAnimator.setStartDelay(150);
+ workspaceAnimator.setDuration(333);
+ workspaceAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+
+ // Animate the shelf
+ AllAppsScrim allAppsScrim = mLauncher.findViewById(R.id.all_apps_scrim);
+ View hotseat = mLauncher.getHotseat();
+ final float endY = mShelfMinValue;
+ int startY = hotseat.getMeasuredHeight()
+ + (allAppsScrim.getShadowBitmap().getHeight() / 2);
+ hotseat.setTranslationY(startY);
+ allAppsScrim.setTranslationY(startY);
+
+ AnimatorSet hotseatSlideIn = new AnimatorSet();
+ hotseatSlideIn.play(ObjectAnimator.ofFloat(hotseat, View.TRANSLATION_Y, startY, endY));
+ hotseatSlideIn.play(ObjectAnimator.ofFloat(allAppsScrim, SCRIM_PROGRESS, startY, endY));
+ hotseatSlideIn.setStartDelay(150);
+ hotseatSlideIn.setDuration(317);
+ hotseatSlideIn.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+
+ AnimatorSet hotseatOvershoot = new AnimatorSet();
+ hotseatOvershoot.play(ObjectAnimator.ofFloat(hotseat, View.TRANSLATION_Y, endY, 0));
+ hotseatOvershoot.play(ObjectAnimator.ofFloat(allAppsScrim, SCRIM_PROGRESS, endY, 0));
+ hotseatOvershoot.setDuration(153);
+ hotseatOvershoot.setInterpolator(Interpolators.OVERSHOOT_0);
+
+ AnimatorSet resumeLauncherAnimation = new AnimatorSet();
+ resumeLauncherAnimation.play(workspaceAnimator);
+ resumeLauncherAnimation.playSequentially(hotseatSlideIn, hotseatOvershoot);
+ return resumeLauncherAnimation;
+ }
+ }
+
+ /**
+ * Helper method that allows us to get interpolated values for embedded
+ * animations with a delay and/or different duration.
+ */
+ private static float getValue(float start, float end, float delay, float duration,
+ float currentPlayTime, Interpolator i) {
+ float time = Math.max(0, currentPlayTime - delay);
+ float newPercent = Math.min(1f, time / duration);
+ newPercent = i.getInterpolation(newPercent);
+ return end * newPercent + start * (1 - newPercent);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
index c4ffc0f..d086e74 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/UiFactory.java
@@ -31,7 +31,6 @@
import com.android.launcher3.util.TouchController;
import com.android.quickstep.RecentsView;
import com.android.systemui.shared.recents.view.RecentsTransition;
-import com.android.systemui.shared.system.RemoteAnimationAdapterCompat;
public class UiFactory {
@@ -89,4 +88,12 @@
return launcher.getDefaultActivityLaunchOptions(v);
}
}
+
+ public static void registerRemoteAnimations(Launcher launcher) {
+ try {
+ new LauncherAppTransitionManager(launcher).registerRemoteAnimations();
+ } catch (NoClassDefFoundError e) {
+ // Gracefully fall back if the user's platform doesn't have the latest changes
+ }
+ }
}
diff --git a/src/com/android/launcher3/InfoDropTarget.java b/src/com/android/launcher3/InfoDropTarget.java
index 289242f..e52fd76 100644
--- a/src/com/android/launcher3/InfoDropTarget.java
+++ b/src/com/android/launcher3/InfoDropTarget.java
@@ -70,7 +70,7 @@
Rect sourceBounds, Bundle opts) {
if (info instanceof PromiseAppInfo) {
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
- context.startActivity(promiseAppInfo.getMarketIntent());
+ context.startActivity(promiseAppInfo.getMarketIntent(context));
return null;
}
ComponentName componentName = null;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 32342b2..5db0a3b 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -403,6 +403,10 @@
getSystemUiController().updateUiState(SystemUiController.UI_STATE_BASE_WINDOW,
Themes.getAttrBoolean(this, R.attr.isWorkspaceDarkText));
+ if (!isInMultiWindowModeCompat()) {
+ UiFactory.registerRemoteAnimations(this);
+ }
+
if (mLauncherCallbacks != null) {
mLauncherCallbacks.onCreate(savedInstanceState);
}
@@ -1739,7 +1743,7 @@
private void startMarketIntentForPackage(View v, String packageName) {
ItemInfo item = (ItemInfo) v.getTag();
- Intent intent = PackageManagerHelper.getMarketIntent(packageName);
+ Intent intent = new PackageManagerHelper(v.getContext()).getMarketIntent(packageName);
startActivitySafely(v, intent, item);
}
@@ -1804,7 +1808,7 @@
Intent intent;
if (item instanceof PromiseAppInfo) {
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) item;
- intent = promiseAppInfo.getMarketIntent();
+ intent = promiseAppInfo.getMarketIntent(this);
} else {
intent = item.getIntent();
}
diff --git a/src/com/android/launcher3/PromiseAppInfo.java b/src/com/android/launcher3/PromiseAppInfo.java
index 07515d0..ea9f752 100644
--- a/src/com/android/launcher3/PromiseAppInfo.java
+++ b/src/com/android/launcher3/PromiseAppInfo.java
@@ -16,6 +16,7 @@
package com.android.launcher3;
+import android.content.Context;
import android.content.Intent;
import android.support.annotation.NonNull;
@@ -46,7 +47,7 @@
return shortcut;
}
- public Intent getMarketIntent() {
- return PackageManagerHelper.getMarketIntent(componentName.getPackageName());
+ public Intent getMarketIntent(Context context) {
+ return new PackageManagerHelper(context).getMarketIntent(componentName.getPackageName());
}
}
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index f3a3539..ee0dba6 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -20,6 +20,7 @@
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
+import android.view.animation.OvershootInterpolator;
import android.view.animation.PathInterpolator;
@@ -43,6 +44,9 @@
public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
public static final Interpolator AGGRESSIVE_EASE = new PathInterpolator(0.2f, 0f, 0f, 1f);
+ public static final Interpolator AGGRESSIVE_EASE_IN_OUT = new PathInterpolator(0.8f,0, 0.4f, 1);
+
+ public static final Interpolator OVERSHOOT_0 = new OvershootInterpolator(0);
/**
* Inversion of zInterpolate, compounded with an ease-out.
diff --git a/src/com/android/launcher3/popup/SystemShortcut.java b/src/com/android/launcher3/popup/SystemShortcut.java
index 83cbf59..d2bcd18 100644
--- a/src/com/android/launcher3/popup/SystemShortcut.java
+++ b/src/com/android/launcher3/popup/SystemShortcut.java
@@ -82,7 +82,7 @@
@Override
public void onClick(View view) {
Rect sourceBounds = launcher.getViewBounds(view);
- Bundle opts = launcher.getActivityLaunchOptions(view, true);
+ Bundle opts = launcher.getActivityLaunchOptions(view, false);
InfoDropTarget.startDetailsActivityForInfo(itemInfo, launcher, sourceBounds, opts);
launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
ControlType.APPINFO_TARGET, view);
@@ -115,8 +115,8 @@
public View.OnClickListener createOnClickListener(Launcher launcher, ItemInfo itemInfo) {
return view -> {
- Intent intent = PackageManagerHelper.getMarketIntent(itemInfo
- .getTargetComponent().getPackageName());
+ Intent intent = new PackageManagerHelper(view.getContext()).getMarketIntent(
+ itemInfo.getTargetComponent().getPackageName());
launcher.startActivitySafely(view, intent, itemInfo);
AbstractFloatingView.closeAllOpenViews(launcher);
};
diff --git a/src/com/android/launcher3/util/PackageManagerHelper.java b/src/com/android/launcher3/util/PackageManagerHelper.java
index 13034dd..81df153 100644
--- a/src/com/android/launcher3/util/PackageManagerHelper.java
+++ b/src/com/android/launcher3/util/PackageManagerHelper.java
@@ -143,13 +143,15 @@
return false;
}
- public static Intent getMarketIntent(String packageName) {
+ public Intent getMarketIntent(String packageName) {
return new Intent(Intent.ACTION_VIEW)
.setData(new Uri.Builder()
.scheme("market")
.authority("details")
.appendQueryParameter("id", packageName)
- .build());
+ .build())
+ .putExtra(Intent.EXTRA_REFERRER, new Uri.Builder().scheme("android-app")
+ .authority(mContext.getPackageName()).build());
}
/**
diff --git a/src/com/android/launcher3/views/AllAppsScrim.java b/src/com/android/launcher3/views/AllAppsScrim.java
index cc73182..6cd40fd 100644
--- a/src/com/android/launcher3/views/AllAppsScrim.java
+++ b/src/com/android/launcher3/views/AllAppsScrim.java
@@ -23,6 +23,7 @@
import android.graphics.Rect;
import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet;
+import android.util.Property;
import android.view.View;
import com.android.launcher3.DeviceProfile;
@@ -60,11 +61,25 @@
private final NinePatchDrawHelper mShadowHelper = new NinePatchDrawHelper();
+ private float mProgress;
private int mFillAlpha;
private float mDrawHeight;
private float mDrawOffsetY;
+ public static final Property<AllAppsScrim, Float> SCRIM_PROGRESS =
+ new Property<AllAppsScrim, Float>(Float.class, "allAppsScrimProgress") {
+ @Override
+ public Float get(AllAppsScrim allAppsScrim) {
+ return allAppsScrim.getProgress();
+ }
+
+ @Override
+ public void set(AllAppsScrim allAppsScrim, Float progress) {
+ allAppsScrim.setProgress(progress);
+ }
+ };
+
public AllAppsScrim(Context context) {
this(context, null);
}
@@ -109,6 +124,10 @@
return result;
}
+ public Bitmap getShadowBitmap() {
+ return mShadowBitmap;
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -154,18 +173,24 @@
}
public void setProgress(float translateY, float alpha) {
- float newAlpha = Math.round(alpha * mAlphaRange + mMinAlpha);
+ int newAlpha = Math.round(alpha * mAlphaRange + mMinAlpha);
+ if (newAlpha != mFillAlpha) {
+ mFillAlpha = newAlpha;
+ mFillPaint.setAlpha(mFillAlpha);
+ invalidateDrawRect();
+ }
+
+ setProgress(translateY);
+ }
+
+ public void setProgress(float translateY) {
// Negative translation means the scrim is moving up. For negative translation, we change
// draw offset as it requires redraw (since more area of the scrim needs to be shown). For
// position translation, we simply translate the scrim down as it avoids invalidate and
// hence could be optimized by the platform.
float drawOffsetY = Math.min(translateY, 0);
- if (newAlpha != mFillAlpha || drawOffsetY != mDrawOffsetY) {
- invalidateDrawRect();
-
- mFillAlpha = Math.round(alpha * mAlphaRange + mMinAlpha);
- mFillPaint.setAlpha(mFillAlpha);
+ if (drawOffsetY != mDrawOffsetY) {
mDrawOffsetY = drawOffsetY;
invalidateDrawRect();
}
@@ -173,6 +198,10 @@
setTranslationY(Math.max(translateY, 0));
}
+ public float getProgress() {
+ return mProgress;
+ }
+
private void invalidateDrawRect() {
mDrawRect.top = (int) (getHeight()
+ mDrawOffsetY - mDrawHeight + mPadding.top - mShadowBlur - 0.5f);
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
index 0488fae..c857bf6 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java
@@ -18,21 +18,15 @@
import static com.android.launcher3.LauncherState.OVERVIEW;
-import android.app.ActivityOptions;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PointF;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.View.AccessibilityDelegate;
-import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherStateManager.StateHandler;
-import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
import com.android.launcher3.graphics.BitmapRenderer;
import com.android.launcher3.util.TouchController;
@@ -71,4 +65,6 @@
public static Bundle getActivityLaunchOptions(Launcher launcher, View v) {
return launcher.getDefaultActivityLaunchOptions(v);
}
+
+ public static void registerRemoteAnimations(Launcher launcher) { }
}