diff options
Diffstat (limited to 'src/com/android/launcher3')
9 files changed, 108 insertions, 49 deletions
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 491e5de85..80860455c 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -446,12 +446,16 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override public void reapplyUi() { + reapplyUi(true /* cancelCurrentAnimation */); + } + + public void reapplyUi(boolean cancelCurrentAnimation) { if (supportsFakeLandscapeUI()) { mRotationMode = mStableDeviceProfile == null ? RotationMode.NORMAL : UiFactory.getRotationMode(mDeviceProfile); } getRootView().dispatchInsets(); - getStateManager().reapplyState(true /* cancelCurrentAnimation */); + getStateManager().reapplyState(cancelCurrentAnimation); } @Override diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java index 848e19fb5..f67350884 100644 --- a/src/com/android/launcher3/LauncherStateManager.java +++ b/src/com/android/launcher3/LauncherStateManager.java @@ -24,7 +24,8 @@ import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.os.Handler; import android.os.Looper; -import android.util.Log; + +import androidx.annotation.IntDef; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; @@ -32,7 +33,6 @@ import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.PropertySetter; import com.android.launcher3.anim.PropertySetter.AnimatedPropertySetter; import com.android.launcher3.compat.AccessibilityManagerCompat; -import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.uioverrides.UiFactory; import java.io.PrintWriter; @@ -40,8 +40,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; -import androidx.annotation.IntDef; - /** * TODO: figure out what kind of tests we can write for this * diff --git a/src/com/android/launcher3/anim/AlphaUpdateListener.java b/src/com/android/launcher3/anim/AlphaUpdateListener.java index 8ac9d662c..eabd28369 100644 --- a/src/com/android/launcher3/anim/AlphaUpdateListener.java +++ b/src/com/android/launcher3/anim/AlphaUpdateListener.java @@ -27,7 +27,7 @@ import android.view.ViewGroup; */ public class AlphaUpdateListener extends AnimationSuccessListener implements AnimatorUpdateListener { - private static final float ALPHA_CUTOFF_THRESHOLD = 0.01f; + public static final float ALPHA_CUTOFF_THRESHOLD = 0.01f; private View mView; diff --git a/src/com/android/launcher3/anim/AnimatorPlaybackController.java b/src/com/android/launcher3/anim/AnimatorPlaybackController.java index 2c440bba1..4a52795f8 100644 --- a/src/com/android/launcher3/anim/AnimatorPlaybackController.java +++ b/src/com/android/launcher3/anim/AnimatorPlaybackController.java @@ -26,15 +26,15 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.util.Log; +import androidx.dynamicanimation.animation.DynamicAnimation; +import androidx.dynamicanimation.animation.SpringAnimation; + import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; -import androidx.dynamicanimation.animation.DynamicAnimation; -import androidx.dynamicanimation.animation.SpringAnimation; - /** * Helper class to control the playback of an {@link AnimatorSet}, with custom interpolators * and durations. @@ -250,6 +250,17 @@ public abstract class AnimatorPlaybackController implements ValueAnimator.Animat } } + /** + * Sets mOnCancelRunnable = null before dispatching the cancel and restoring the runnable. This + * is intended to be used only if you need to cancel but want to defer cleaning up yourself. + */ + public void dispatchOnCancelWithoutCancelRunnable() { + Runnable onCancel = mOnCancelRunnable; + setOnCancelRunnable(null); + dispatchOnCancel(); + setOnCancelRunnable(onCancel); + } + public void dispatchOnCancel() { dispatchOnCancelRecursively(mAnim); } @@ -283,10 +294,6 @@ public abstract class AnimatorPlaybackController implements ValueAnimator.Animat mOnCancelRunnable = runnable; } - public Runnable getOnCancelRunnable() { - return mOnCancelRunnable; - } - public void skipToEnd() { mSkipToEnd = true; for (SpringAnimation spring : mSprings) { diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java index c45cd85aa..fccc12090 100644 --- a/src/com/android/launcher3/anim/Interpolators.java +++ b/src/com/android/launcher3/anim/Interpolators.java @@ -39,6 +39,7 @@ public class Interpolators { public static final Interpolator LINEAR = new LinearInterpolator(); public static final Interpolator ACCEL = new AccelerateInterpolator(); + public static final Interpolator ACCEL_0_75 = new AccelerateInterpolator(0.75f); public static final Interpolator ACCEL_1_5 = new AccelerateInterpolator(1.5f); public static final Interpolator ACCEL_2 = new AccelerateInterpolator(2); @@ -48,6 +49,7 @@ public class Interpolators { public static final Interpolator DEACCEL_2 = new DecelerateInterpolator(2); public static final Interpolator DEACCEL_2_5 = new DecelerateInterpolator(2.5f); public static final Interpolator DEACCEL_3 = new DecelerateInterpolator(3f); + public static final Interpolator DEACCEL_5 = new DecelerateInterpolator(5f); public static final Interpolator ACCEL_DEACCEL = new AccelerateDecelerateInterpolator(); diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 6b9e20525..0bd2c9af7 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -148,7 +148,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo public ExtendedEditText mFolderName; private PageIndicatorDots mPageIndicator; - private View mFooter; + protected View mFooter; private int mFooterHeight; // Cell ranks used for drag and drop @@ -991,7 +991,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo lp.y = top; } - private int getContentAreaHeight() { + protected int getContentAreaHeight() { DeviceProfile grid = mLauncher.getDeviceProfile(); int maxContentAreaHeight = grid.availableHeightPx - grid.getTotalWorkspacePadding().y - mFooterHeight; diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java index 9eb06938a..1310d374e 100644 --- a/src/com/android/launcher3/folder/FolderAnimationManager.java +++ b/src/com/android/launcher3/folder/FolderAnimationManager.java @@ -59,6 +59,8 @@ import java.util.List; */ public class FolderAnimationManager { + private static final int FOLDER_NAME_ALPHA_DURATION = 32; + private Folder mFolder; private FolderPagedView mContent; private GradientDrawable mFolderBackground; @@ -130,11 +132,19 @@ public class FolderAnimationManager { * scaleRelativeToDragLayer; final float finalScale = 1f; float scale = mIsOpening ? initialScale : finalScale; - mFolder.setScaleX(scale); - mFolder.setScaleY(scale); mFolder.setPivotX(0); mFolder.setPivotY(0); + // Scale the contents of the folder. + mFolder.mContent.setScaleX(scale); + mFolder.mContent.setScaleY(scale); + mFolder.mContent.setPivotX(0); + mFolder.mContent.setPivotY(0); + mFolder.mFooter.setScaleX(scale); + mFolder.mFooter.setScaleY(scale); + mFolder.mFooter.setPivotX(0); + mFolder.mFooter.setPivotY(0); + // We want to create a small X offset for the preview items, so that they follow their // expected path to their final locations. ie. an icon should not move right, if it's final // location is to its left. This value is arbitrarily defined. @@ -143,14 +153,13 @@ public class FolderAnimationManager { previewItemOffsetX = (int) (lp.width * initialScale - initialSize - previewItemOffsetX); } - final int paddingOffsetX = (int) ((mFolder.getPaddingLeft() + mContent.getPaddingLeft()) - * initialScale); - final int paddingOffsetY = (int) ((mFolder.getPaddingTop() + mContent.getPaddingTop()) - * initialScale); + final int paddingOffsetX = (int) (mContent.getPaddingLeft() * initialScale); + final int paddingOffsetY = (int) (mContent.getPaddingTop() * initialScale); - int initialX = folderIconPos.left + mPreviewBackground.getOffsetX() - paddingOffsetX - - previewItemOffsetX; - int initialY = folderIconPos.top + mPreviewBackground.getOffsetY() - paddingOffsetY; + int initialX = folderIconPos.left + mFolder.getPaddingLeft() + + mPreviewBackground.getOffsetX() - paddingOffsetX - previewItemOffsetX; + int initialY = folderIconPos.top + mFolder.getPaddingTop() + + mPreviewBackground.getOffsetY() - paddingOffsetY; final float xDistance = initialX - lp.x; final float yDistance = initialY - lp.y; @@ -164,11 +173,10 @@ public class FolderAnimationManager { // Set up the reveal animation that clips the Folder. int totalOffsetX = paddingOffsetX + previewItemOffsetX; - Rect startRect = new Rect( - Math.round(totalOffsetX / initialScale), - Math.round(paddingOffsetY / initialScale), - Math.round((totalOffsetX + initialSize) / initialScale), - Math.round((paddingOffsetY + initialSize) / initialScale)); + Rect startRect = new Rect(totalOffsetX, + paddingOffsetY, + Math.round((totalOffsetX + initialSize)), + Math.round((paddingOffsetY + initialSize))); Rect endRect = new Rect(0, 0, lp.width, lp.height); float finalRadius = ResourceUtils.pxFromDp(2, mContext.getResources().getDisplayMetrics()); @@ -189,17 +197,46 @@ public class FolderAnimationManager { play(a, getAnimator(mFolder, View.TRANSLATION_X, xDistance, 0f)); play(a, getAnimator(mFolder, View.TRANSLATION_Y, yDistance, 0f)); - play(a, getAnimator(mFolder, SCALE_PROPERTY, initialScale, finalScale)); + play(a, getAnimator(mFolder.mContent, SCALE_PROPERTY, initialScale, finalScale)); + play(a, getAnimator(mFolder.mFooter, SCALE_PROPERTY, initialScale, finalScale)); play(a, getAnimator(mFolderBackground, "color", initialColor, finalColor)); play(a, mFolderIcon.mFolderName.createTextAlphaAnimator(!mIsOpening)); play(a, getShape().createRevealAnimator( mFolder, startRect, endRect, finalRadius, !mIsOpening)); + // Fade in the folder name, as the text can overlap the icons when grid size is small. + mFolder.mFolderName.setAlpha(mIsOpening ? 0f : 1f); + play(a, getAnimator(mFolder.mFolderName, View.ALPHA, 0, 1), + mIsOpening ? FOLDER_NAME_ALPHA_DURATION : 0, + mIsOpening ? mDuration - FOLDER_NAME_ALPHA_DURATION : FOLDER_NAME_ALPHA_DURATION); + + // Translate the footer so that it tracks the bottom of the content. + float normalHeight = mFolder.getContentAreaHeight(); + float scaledHeight = normalHeight * initialScale; + float diff = normalHeight - scaledHeight; + play(a, getAnimator(mFolder.mFooter, View.TRANSLATION_Y, -diff, 0f)); // Animate the elevation midway so that the shadow is not noticeable in the background. int midDuration = mDuration / 2; Animator z = getAnimator(mFolder, View.TRANSLATION_Z, -mFolder.getElevation(), 0); play(a, z, mIsOpening ? midDuration : 0, midDuration); + + // Store clip variables + CellLayout cellLayout = mContent.getCurrentCellLayout(); + boolean folderClipChildren = mFolder.getClipChildren(); + boolean folderClipToPadding = mFolder.getClipToPadding(); + boolean contentClipChildren = mContent.getClipChildren(); + boolean contentClipToPadding = mContent.getClipToPadding(); + boolean cellLayoutClipChildren = cellLayout.getClipChildren(); + boolean cellLayoutClipPadding = cellLayout.getClipToPadding(); + + mFolder.setClipChildren(false); + mFolder.setClipToPadding(false); + mContent.setClipChildren(false); + mContent.setClipToPadding(false); + cellLayout.setClipChildren(false); + cellLayout.setClipToPadding(false); + a.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -207,8 +244,20 @@ public class FolderAnimationManager { mFolder.setTranslationX(0.0f); mFolder.setTranslationY(0.0f); mFolder.setTranslationZ(0.0f); - mFolder.setScaleX(1f); - mFolder.setScaleY(1f); + mFolder.mContent.setScaleX(1f); + mFolder.mContent.setScaleY(1f); + mFolder.mFooter.setScaleX(1f); + mFolder.mFooter.setScaleY(1f); + mFolder.mFooter.setTranslationX(0f); + mFolder.mFolderName.setAlpha(1f); + + mFolder.setClipChildren(folderClipChildren); + mFolder.setClipToPadding(folderClipToPadding); + mContent.setClipChildren(contentClipChildren); + mContent.setClipToPadding(contentClipToPadding); + cellLayout.setClipChildren(cellLayoutClipChildren); + cellLayout.setClipToPadding(cellLayoutClipPadding); + } }); diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index 60f6ee9c5..f40f9762d 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -413,10 +413,7 @@ public abstract class AbstractStateChangeTouchController } else { // Let the state manager know that the animation didn't go to the target state, // but don't cancel ourselves (we already clean up when the animation completes). - Runnable onCancel = mCurrentAnimation.getOnCancelRunnable(); - mCurrentAnimation.setOnCancelRunnable(null); - mCurrentAnimation.dispatchOnCancel(); - mCurrentAnimation.setOnCancelRunnable(onCancel); + mCurrentAnimation.dispatchOnCancelWithoutCancelRunnable(); endProgress = 0; if (progress <= 0) { diff --git a/src/com/android/launcher3/views/FloatingIconView.java b/src/com/android/launcher3/views/FloatingIconView.java index 45c0d9097..49d94f06e 100644 --- a/src/com/android/launcher3/views/FloatingIconView.java +++ b/src/com/android/launcher3/views/FloatingIconView.java @@ -560,7 +560,7 @@ public class FloatingIconView extends View implements * Checks if the icon result is loaded. If true, we set the icon immediately. Else, we add a * callback to set the icon once the icon result is loaded. */ - private void checkIconResult(View originalView, boolean isOpening) { + private void checkIconResult(View originalView) { CancellationSignal cancellationSignal = new CancellationSignal(); if (mIconLoadResult == null) { @@ -572,9 +572,7 @@ public class FloatingIconView extends View implements if (mIconLoadResult.isIconLoaded) { setIcon(originalView, mIconLoadResult.drawable, mIconLoadResult.badge, mIconLoadResult.iconOffset); - if (isOpening) { - hideOriginalView(originalView); - } + hideOriginalView(originalView); } else { mIconLoadResult.onIconLoaded = () -> { if (cancellationSignal.isCanceled()) { @@ -583,12 +581,8 @@ public class FloatingIconView extends View implements setIcon(originalView, mIconLoadResult.drawable, mIconLoadResult.badge, mIconLoadResult.iconOffset); - setVisibility(VISIBLE); - if (isOpening) { - // Delay swapping views until the icon is loaded to prevent a flash. - hideOriginalView(originalView); - } + hideOriginalView(originalView); }; mLoadIconSignal = cancellationSignal; } @@ -596,9 +590,9 @@ public class FloatingIconView extends View implements } private void hideOriginalView(View originalView) { - if (originalView instanceof BubbleTextView) { - ((BubbleTextView) originalView).setIconVisible(false); - ((BubbleTextView) originalView).setForceHideDot(true); + if (originalView instanceof IconLabelDotView) { + ((IconLabelDotView) originalView).setIconVisible(false); + ((IconLabelDotView) originalView).setForceHideDot(true); } else { originalView.setVisibility(INVISIBLE); } @@ -674,6 +668,9 @@ public class FloatingIconView extends View implements } public void fastFinish() { + if (mLoadIconSignal != null) { + mLoadIconSignal.cancel(); + } if (mEndRunnable != null) { mEndRunnable.run(); mEndRunnable = null; @@ -689,6 +686,10 @@ public class FloatingIconView extends View implements if (mIconLoadResult != null && mIconLoadResult.isIconLoaded) { setVisibility(View.VISIBLE); } + if (!mIsOpening) { + // When closing an app, we want the item on the workspace to be invisible immediately + hideOriginalView(mOriginalIcon); + } } @Override @@ -798,7 +799,7 @@ public class FloatingIconView extends View implements // Must be called after the fastFinish listener and end runnable is created so that // the icon is not left in a hidden state. if (shouldLoadIcon) { - view.checkIconResult(originalView, isOpening); + view.checkIconResult(originalView); } return view; @@ -842,6 +843,7 @@ public class FloatingIconView extends View implements @Override public void onAnimationStart(Animator animation) { btv.setIconVisible(true); + btv.setForceHideDot(true); } }); fade.play(ObjectAnimator.ofInt(btv.getIcon(), DRAWABLE_ALPHA, 0, 255)); |