Loading quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +98 −54 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.graphics.drawable.Drawable; import android.os.CancellationSignal; import android.os.Handler; import android.os.Looper; import android.os.SystemProperties; import android.util.Pair; import android.view.View; Loading Loading @@ -99,6 +100,9 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans private static final String TAG = "QuickstepTransition"; private static final boolean ENABLE_SHELL_STARTING_SURFACE = SystemProperties.getBoolean("persist.debug.shell_starting_surface", false); /** Duration of status bar animations. */ public static final int STATUS_BAR_TRANSITION_DURATION = 120; Loading Loading @@ -442,9 +446,9 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans RemoteAnimationTargetCompat[] appTargets, RemoteAnimationTargetCompat[] wallpaperTargets, Rect windowTargetBounds, boolean toggleVisibility) { RectF bounds = new RectF(); RectF launcherIconBounds = new RectF(); FloatingIconView floatingView = FloatingIconView.getFloatingIconView(mLauncher, v, toggleVisibility, bounds, true /* isOpening */); toggleVisibility, launcherIconBounds, true /* isOpening */); Rect crop = new Rect(); Matrix matrix = new Matrix(); Loading @@ -458,11 +462,17 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans mDragLayer.getLocationOnScreen(dragLayerBounds); AnimOpenProperties prop = new AnimOpenProperties(mLauncher.getResources(), mDeviceProfile, windowTargetBounds, bounds, v, dragLayerBounds); windowTargetBounds, launcherIconBounds, v, dragLayerBounds[0], dragLayerBounds[1]); int left = (int) (prop.cropCenterXStart - prop.cropWidthStart / 2); int top = (int) (prop.cropCenterYStart - prop.cropHeightStart / 2); int right = (int) (left + prop.cropWidthStart); int bottom = (int) (top + prop.cropHeightStart); // Set the crop here so we can calculate the corner radius below. crop.set(left, top, right, bottom); RectF targetBounds = new RectF(windowTargetBounds); RectF iconBounds = new RectF(); RectF temp = new RectF(); RectF floatingIconBounds = new RectF(); RectF tmpRectF = new RectF(); Point tmpPos = new Point(); AnimatorSet animatorSet = new AnimatorSet(); Loading @@ -481,68 +491,79 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans }); final float initialWindowRadius = supportsRoundedCornersOnWindows(mLauncher.getResources()) ? prop.startCrop / 2f : 0f; ? Math.max(crop.width(), crop.height()) / 2f : 0f; final float finalWindowRadius = mDeviceProfile.isMultiWindowMode ? 0 : getWindowCornerRadius(mLauncher.getResources()); appAnimator.addUpdateListener(new MultiValueUpdateListener() { FloatProp mDx = new FloatProp(0, prop.dX, 0, prop.xDuration, AGGRESSIVE_EASE); FloatProp mDy = new FloatProp(0, prop.dY, 0, prop.yDuration, AGGRESSIVE_EASE); FloatProp mScale = new FloatProp(prop.initialAppIconScale, FloatProp mIconScaleToFitScreen = new FloatProp(prop.initialAppIconScale, prop.finalAppIconScale, 0, APP_LAUNCH_DURATION, EXAGGERATED_EASE); FloatProp mIconAlpha = new FloatProp(prop.iconAlphaStart, 0f, APP_LAUNCH_ALPHA_START_DELAY, prop.alphaDuration, LINEAR); FloatProp mCroppedSize = new FloatProp(prop.startCrop, prop.endCrop, 0, CROP_DURATION, EXAGGERATED_EASE); FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius, 0, RADIUS_DURATION, EXAGGERATED_EASE); FloatProp mShadowRadius = new FloatProp(0, mMaxShadowRadius, 0, APP_LAUNCH_DURATION, EXAGGERATED_EASE); FloatProp mCropRectCenterX = new FloatProp(prop.cropCenterXStart, prop.cropCenterXEnd, 0, CROP_DURATION, EXAGGERATED_EASE); FloatProp mCropRectCenterY = new FloatProp(prop.cropCenterYStart, prop.cropCenterYEnd, 0, CROP_DURATION, EXAGGERATED_EASE); FloatProp mCropRectWidth = new FloatProp(prop.cropWidthStart, prop.cropWidthEnd, 0, CROP_DURATION, EXAGGERATED_EASE); FloatProp mCropRectHeight = new FloatProp(prop.cropHeightStart, prop.cropHeightEnd, 0, CROP_DURATION, EXAGGERATED_EASE); @Override public void onUpdate(float percent) { // Calculate the size of the scaled icon. float width = bounds.width() * mScale.value; float height = bounds.height() * mScale.value; // Animate the crop so that it starts off as a square. final int cropWidth; final int cropHeight; if (mDeviceProfile.isVerticalBarLayout()) { cropWidth = (int) mCroppedSize.value; cropHeight = windowTargetBounds.height(); } else { cropWidth = windowTargetBounds.width(); cropHeight = (int) mCroppedSize.value; } crop.set(0, 0, cropWidth, cropHeight); float iconWidth = launcherIconBounds.width() * mIconScaleToFitScreen.value; float iconHeight = launcherIconBounds.height() * mIconScaleToFitScreen.value; int left = (int) (mCropRectCenterX.value - mCropRectWidth.value / 2); int top = (int) (mCropRectCenterY.value - mCropRectHeight.value / 2); int right = (int) (left + mCropRectWidth.value); int bottom = (int) (top + mCropRectHeight.value); crop.set(left, top, right, bottom); final int windowCropWidth = crop.width(); final int windowCropHeight = crop.height(); // Scale the size of the icon to match the size of the window crop. float scaleX = width / cropWidth; float scaleY = height / cropHeight; float scaleX = iconWidth / windowCropWidth; float scaleY = iconHeight / windowCropHeight; float scale = Math.min(1f, Math.max(scaleX, scaleY)); float scaledCropWidth = cropWidth * scale; float scaledCropHeight = cropHeight * scale; float offsetX = (scaledCropWidth - width) / 2; float offsetY = (scaledCropHeight - height) / 2; float scaledCropWidth = windowCropWidth * scale; float scaledCropHeight = windowCropHeight * scale; float offsetX = (scaledCropWidth - iconWidth) / 2; float offsetY = (scaledCropHeight - iconHeight) / 2; // Calculate the window position to match the icon position. temp.set(bounds); temp.offset(dragLayerBounds[0], dragLayerBounds[1]); temp.offset(mDx.value, mDy.value); Utilities.scaleRectFAboutCenter(temp, mScale.value); float windowTransX0 = temp.left - offsetX; float windowTransY0 = temp.top - offsetY; tmpRectF.set(launcherIconBounds); tmpRectF.offset(dragLayerBounds[0], dragLayerBounds[1]); tmpRectF.offset(mDx.value, mDy.value); Utilities.scaleRectFAboutCenter(tmpRectF, mIconScaleToFitScreen.value); float windowTransX0 = tmpRectF.left - offsetX; float windowTransY0 = tmpRectF.top - offsetY; if (ENABLE_SHELL_STARTING_SURFACE) { windowTransX0 -= crop.left * scale; windowTransY0 -= crop.top * scale; } // Calculate the icon position. iconBounds.set(bounds); iconBounds.offset(mDx.value, mDy.value); Utilities.scaleRectFAboutCenter(iconBounds, mScale.value); iconBounds.left -= offsetX; iconBounds.top -= offsetY; iconBounds.right += offsetX; iconBounds.bottom += offsetY; floatingIconBounds.set(launcherIconBounds); floatingIconBounds.offset(mDx.value, mDy.value); Utilities.scaleRectFAboutCenter(floatingIconBounds, mIconScaleToFitScreen.value); floatingIconBounds.left -= offsetX; floatingIconBounds.top -= offsetY; floatingIconBounds.right += offsetX; floatingIconBounds.bottom += offsetY; SurfaceParams[] params = new SurfaceParams[appTargets.length]; for (int i = appTargets.length - 1; i >= 0; i--) { Loading @@ -553,7 +574,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans matrix.setScale(scale, scale); matrix.postTranslate(windowTransX0, windowTransY0); floatingView.update(iconBounds, mIconAlpha.value, percent, 0f, floatingView.update(floatingIconBounds, mIconAlpha.value, percent, 0f, mWindowRadius.value * scale, true /* isOpening */); builder.withMatrix(matrix) .withWindowCrop(crop) Loading Loading @@ -932,8 +953,15 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans */ static class AnimOpenProperties { public final float startCrop; public final float endCrop; public final int cropCenterXStart; public final int cropCenterYStart; public final int cropWidthStart; public final int cropHeightStart; public final int cropCenterXEnd; public final int cropCenterYEnd; public final int cropWidthEnd; public final int cropHeightEnd; public final float dX; public final float dY; Loading @@ -948,7 +976,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans public final float iconAlphaStart; AnimOpenProperties(Resources r, DeviceProfile dp, Rect windowTargetBounds, RectF launcherIconBounds, View view, int[] dragLayerBounds) { RectF launcherIconBounds, View view, int dragLayerLeft, int dragLayerTop) { // Scale the app icon to take up the entire screen. This simplifies the math when // animating the app window position / scale. float smallestSize = Math.min(windowTargetBounds.height(), windowTargetBounds.width()); Loading @@ -966,8 +994,8 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans finalAppIconScale = Math.max(maxScaleX, maxScaleY); // Animate the app icon to the center of the window bounds in screen coordinates. float centerX = windowTargetBounds.centerX() - dragLayerBounds[0]; float centerY = windowTargetBounds.centerY() - dragLayerBounds[1]; float centerX = windowTargetBounds.centerX() - dragLayerLeft; float centerY = windowTargetBounds.centerY() - dragLayerTop; dX = centerX - launcherIconBounds.centerX(); dY = centerY - launcherIconBounds.centerY(); Loading @@ -981,15 +1009,31 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans alphaDuration = useUpwardAnimation ? APP_LAUNCH_ALPHA_DURATION : APP_LAUNCH_ALPHA_DOWN_DURATION; if (dp.isVerticalBarLayout()) { startCrop = windowTargetBounds.height(); endCrop = windowTargetBounds.width(); if (ENABLE_SHELL_STARTING_SURFACE) { iconAlphaStart = 0; // TOOD: Share value from shell when available. final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics()); cropCenterXStart = windowTargetBounds.centerX(); cropCenterYStart = windowTargetBounds.centerY(); cropWidthStart = (int) windowIconSize; cropHeightStart = (int) windowIconSize; } else { startCrop = windowTargetBounds.width(); endCrop = windowTargetBounds.height(); iconAlphaStart = 1; cropWidthStart = cropHeightStart = Math.min(windowTargetBounds.width(), windowTargetBounds.height()); cropCenterXStart = cropCenterYStart = Math.min(windowTargetBounds.centerX(), windowTargetBounds.centerY()); } iconAlphaStart = 1f; cropWidthEnd = windowTargetBounds.width(); cropHeightEnd = windowTargetBounds.height(); cropCenterXEnd = windowTargetBounds.centerX(); cropCenterYEnd = windowTargetBounds.centerY(); } } } Loading
quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +98 −54 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import android.graphics.drawable.Drawable; import android.os.CancellationSignal; import android.os.Handler; import android.os.Looper; import android.os.SystemProperties; import android.util.Pair; import android.view.View; Loading Loading @@ -99,6 +100,9 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans private static final String TAG = "QuickstepTransition"; private static final boolean ENABLE_SHELL_STARTING_SURFACE = SystemProperties.getBoolean("persist.debug.shell_starting_surface", false); /** Duration of status bar animations. */ public static final int STATUS_BAR_TRANSITION_DURATION = 120; Loading Loading @@ -442,9 +446,9 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans RemoteAnimationTargetCompat[] appTargets, RemoteAnimationTargetCompat[] wallpaperTargets, Rect windowTargetBounds, boolean toggleVisibility) { RectF bounds = new RectF(); RectF launcherIconBounds = new RectF(); FloatingIconView floatingView = FloatingIconView.getFloatingIconView(mLauncher, v, toggleVisibility, bounds, true /* isOpening */); toggleVisibility, launcherIconBounds, true /* isOpening */); Rect crop = new Rect(); Matrix matrix = new Matrix(); Loading @@ -458,11 +462,17 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans mDragLayer.getLocationOnScreen(dragLayerBounds); AnimOpenProperties prop = new AnimOpenProperties(mLauncher.getResources(), mDeviceProfile, windowTargetBounds, bounds, v, dragLayerBounds); windowTargetBounds, launcherIconBounds, v, dragLayerBounds[0], dragLayerBounds[1]); int left = (int) (prop.cropCenterXStart - prop.cropWidthStart / 2); int top = (int) (prop.cropCenterYStart - prop.cropHeightStart / 2); int right = (int) (left + prop.cropWidthStart); int bottom = (int) (top + prop.cropHeightStart); // Set the crop here so we can calculate the corner radius below. crop.set(left, top, right, bottom); RectF targetBounds = new RectF(windowTargetBounds); RectF iconBounds = new RectF(); RectF temp = new RectF(); RectF floatingIconBounds = new RectF(); RectF tmpRectF = new RectF(); Point tmpPos = new Point(); AnimatorSet animatorSet = new AnimatorSet(); Loading @@ -481,68 +491,79 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans }); final float initialWindowRadius = supportsRoundedCornersOnWindows(mLauncher.getResources()) ? prop.startCrop / 2f : 0f; ? Math.max(crop.width(), crop.height()) / 2f : 0f; final float finalWindowRadius = mDeviceProfile.isMultiWindowMode ? 0 : getWindowCornerRadius(mLauncher.getResources()); appAnimator.addUpdateListener(new MultiValueUpdateListener() { FloatProp mDx = new FloatProp(0, prop.dX, 0, prop.xDuration, AGGRESSIVE_EASE); FloatProp mDy = new FloatProp(0, prop.dY, 0, prop.yDuration, AGGRESSIVE_EASE); FloatProp mScale = new FloatProp(prop.initialAppIconScale, FloatProp mIconScaleToFitScreen = new FloatProp(prop.initialAppIconScale, prop.finalAppIconScale, 0, APP_LAUNCH_DURATION, EXAGGERATED_EASE); FloatProp mIconAlpha = new FloatProp(prop.iconAlphaStart, 0f, APP_LAUNCH_ALPHA_START_DELAY, prop.alphaDuration, LINEAR); FloatProp mCroppedSize = new FloatProp(prop.startCrop, prop.endCrop, 0, CROP_DURATION, EXAGGERATED_EASE); FloatProp mWindowRadius = new FloatProp(initialWindowRadius, finalWindowRadius, 0, RADIUS_DURATION, EXAGGERATED_EASE); FloatProp mShadowRadius = new FloatProp(0, mMaxShadowRadius, 0, APP_LAUNCH_DURATION, EXAGGERATED_EASE); FloatProp mCropRectCenterX = new FloatProp(prop.cropCenterXStart, prop.cropCenterXEnd, 0, CROP_DURATION, EXAGGERATED_EASE); FloatProp mCropRectCenterY = new FloatProp(prop.cropCenterYStart, prop.cropCenterYEnd, 0, CROP_DURATION, EXAGGERATED_EASE); FloatProp mCropRectWidth = new FloatProp(prop.cropWidthStart, prop.cropWidthEnd, 0, CROP_DURATION, EXAGGERATED_EASE); FloatProp mCropRectHeight = new FloatProp(prop.cropHeightStart, prop.cropHeightEnd, 0, CROP_DURATION, EXAGGERATED_EASE); @Override public void onUpdate(float percent) { // Calculate the size of the scaled icon. float width = bounds.width() * mScale.value; float height = bounds.height() * mScale.value; // Animate the crop so that it starts off as a square. final int cropWidth; final int cropHeight; if (mDeviceProfile.isVerticalBarLayout()) { cropWidth = (int) mCroppedSize.value; cropHeight = windowTargetBounds.height(); } else { cropWidth = windowTargetBounds.width(); cropHeight = (int) mCroppedSize.value; } crop.set(0, 0, cropWidth, cropHeight); float iconWidth = launcherIconBounds.width() * mIconScaleToFitScreen.value; float iconHeight = launcherIconBounds.height() * mIconScaleToFitScreen.value; int left = (int) (mCropRectCenterX.value - mCropRectWidth.value / 2); int top = (int) (mCropRectCenterY.value - mCropRectHeight.value / 2); int right = (int) (left + mCropRectWidth.value); int bottom = (int) (top + mCropRectHeight.value); crop.set(left, top, right, bottom); final int windowCropWidth = crop.width(); final int windowCropHeight = crop.height(); // Scale the size of the icon to match the size of the window crop. float scaleX = width / cropWidth; float scaleY = height / cropHeight; float scaleX = iconWidth / windowCropWidth; float scaleY = iconHeight / windowCropHeight; float scale = Math.min(1f, Math.max(scaleX, scaleY)); float scaledCropWidth = cropWidth * scale; float scaledCropHeight = cropHeight * scale; float offsetX = (scaledCropWidth - width) / 2; float offsetY = (scaledCropHeight - height) / 2; float scaledCropWidth = windowCropWidth * scale; float scaledCropHeight = windowCropHeight * scale; float offsetX = (scaledCropWidth - iconWidth) / 2; float offsetY = (scaledCropHeight - iconHeight) / 2; // Calculate the window position to match the icon position. temp.set(bounds); temp.offset(dragLayerBounds[0], dragLayerBounds[1]); temp.offset(mDx.value, mDy.value); Utilities.scaleRectFAboutCenter(temp, mScale.value); float windowTransX0 = temp.left - offsetX; float windowTransY0 = temp.top - offsetY; tmpRectF.set(launcherIconBounds); tmpRectF.offset(dragLayerBounds[0], dragLayerBounds[1]); tmpRectF.offset(mDx.value, mDy.value); Utilities.scaleRectFAboutCenter(tmpRectF, mIconScaleToFitScreen.value); float windowTransX0 = tmpRectF.left - offsetX; float windowTransY0 = tmpRectF.top - offsetY; if (ENABLE_SHELL_STARTING_SURFACE) { windowTransX0 -= crop.left * scale; windowTransY0 -= crop.top * scale; } // Calculate the icon position. iconBounds.set(bounds); iconBounds.offset(mDx.value, mDy.value); Utilities.scaleRectFAboutCenter(iconBounds, mScale.value); iconBounds.left -= offsetX; iconBounds.top -= offsetY; iconBounds.right += offsetX; iconBounds.bottom += offsetY; floatingIconBounds.set(launcherIconBounds); floatingIconBounds.offset(mDx.value, mDy.value); Utilities.scaleRectFAboutCenter(floatingIconBounds, mIconScaleToFitScreen.value); floatingIconBounds.left -= offsetX; floatingIconBounds.top -= offsetY; floatingIconBounds.right += offsetX; floatingIconBounds.bottom += offsetY; SurfaceParams[] params = new SurfaceParams[appTargets.length]; for (int i = appTargets.length - 1; i >= 0; i--) { Loading @@ -553,7 +574,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans matrix.setScale(scale, scale); matrix.postTranslate(windowTransX0, windowTransY0); floatingView.update(iconBounds, mIconAlpha.value, percent, 0f, floatingView.update(floatingIconBounds, mIconAlpha.value, percent, 0f, mWindowRadius.value * scale, true /* isOpening */); builder.withMatrix(matrix) .withWindowCrop(crop) Loading Loading @@ -932,8 +953,15 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans */ static class AnimOpenProperties { public final float startCrop; public final float endCrop; public final int cropCenterXStart; public final int cropCenterYStart; public final int cropWidthStart; public final int cropHeightStart; public final int cropCenterXEnd; public final int cropCenterYEnd; public final int cropWidthEnd; public final int cropHeightEnd; public final float dX; public final float dY; Loading @@ -948,7 +976,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans public final float iconAlphaStart; AnimOpenProperties(Resources r, DeviceProfile dp, Rect windowTargetBounds, RectF launcherIconBounds, View view, int[] dragLayerBounds) { RectF launcherIconBounds, View view, int dragLayerLeft, int dragLayerTop) { // Scale the app icon to take up the entire screen. This simplifies the math when // animating the app window position / scale. float smallestSize = Math.min(windowTargetBounds.height(), windowTargetBounds.width()); Loading @@ -966,8 +994,8 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans finalAppIconScale = Math.max(maxScaleX, maxScaleY); // Animate the app icon to the center of the window bounds in screen coordinates. float centerX = windowTargetBounds.centerX() - dragLayerBounds[0]; float centerY = windowTargetBounds.centerY() - dragLayerBounds[1]; float centerX = windowTargetBounds.centerX() - dragLayerLeft; float centerY = windowTargetBounds.centerY() - dragLayerTop; dX = centerX - launcherIconBounds.centerX(); dY = centerY - launcherIconBounds.centerY(); Loading @@ -981,15 +1009,31 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans alphaDuration = useUpwardAnimation ? APP_LAUNCH_ALPHA_DURATION : APP_LAUNCH_ALPHA_DOWN_DURATION; if (dp.isVerticalBarLayout()) { startCrop = windowTargetBounds.height(); endCrop = windowTargetBounds.width(); if (ENABLE_SHELL_STARTING_SURFACE) { iconAlphaStart = 0; // TOOD: Share value from shell when available. final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics()); cropCenterXStart = windowTargetBounds.centerX(); cropCenterYStart = windowTargetBounds.centerY(); cropWidthStart = (int) windowIconSize; cropHeightStart = (int) windowIconSize; } else { startCrop = windowTargetBounds.width(); endCrop = windowTargetBounds.height(); iconAlphaStart = 1; cropWidthStart = cropHeightStart = Math.min(windowTargetBounds.width(), windowTargetBounds.height()); cropCenterXStart = cropCenterYStart = Math.min(windowTargetBounds.centerX(), windowTargetBounds.centerY()); } iconAlphaStart = 1f; cropWidthEnd = windowTargetBounds.width(); cropHeightEnd = windowTargetBounds.height(); cropCenterXEnd = windowTargetBounds.centerX(); cropCenterYEnd = windowTargetBounds.centerY(); } } }