diff options
Diffstat (limited to 'src/com/android/launcher3/folder/Folder.java')
-rw-r--r-- | src/com/android/launcher3/folder/Folder.java | 184 |
1 files changed, 128 insertions, 56 deletions
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 93c9ea8e3..1601edb44 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -46,6 +46,7 @@ import android.widget.TextView; import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.Alarm; import com.android.launcher3.AppInfo; +import com.android.launcher3.BubbleTextView; import com.android.launcher3.CellLayout; import com.android.launcher3.DeviceProfile; import com.android.launcher3.DragSource; @@ -66,8 +67,9 @@ import com.android.launcher3.UninstallDropTarget.DropTargetSource; import com.android.launcher3.Utilities; import com.android.launcher3.Workspace.ItemOperator; import com.android.launcher3.accessibility.AccessibleDragListenerAdapter; +import com.android.launcher3.anim.AnimationLayerSet; +import com.android.launcher3.anim.CircleRevealOutlineProvider; import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.config.ProviderConfig; import com.android.launcher3.dragndrop.DragController; import com.android.launcher3.dragndrop.DragController.DragListener; import com.android.launcher3.dragndrop.DragLayer; @@ -75,12 +77,12 @@ import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.pageindicators.PageIndicatorDots; import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType; import com.android.launcher3.userevent.nano.LauncherLogProto.Target; -import com.android.launcher3.util.CircleRevealOutlineProvider; import com.android.launcher3.util.Thunk; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.List; /** * Represents a set of icons chosen by the user or generated by the system. @@ -133,8 +135,10 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC @Thunk final ArrayList<View> mItemsInReadingOrder = new ArrayList<View>(); + private AnimatorSet mCurrentAnimator; + private final int mExpandDuration; - private final int mMaterialExpandDuration; + public final int mMaterialExpandDuration; private final int mMaterialExpandStagger; protected final Launcher mLauncher; @@ -501,51 +505,31 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC mState = STATE_SMALL; } - /** - * Opens the user folder described by the specified tag. The opening of the folder - * is animated relative to the specified View. If the View is null, no animation - * is played. - */ - public void animateOpen() { - Folder openFolder = getOpen(mLauncher); - if (openFolder != null && openFolder != this) { - // Close any open folder before opening a folder. - openFolder.close(true); + private void startAnimation(final AnimatorSet a) { + if (mCurrentAnimator != null && mCurrentAnimator.isRunning()) { + mCurrentAnimator.cancel(); } - - DragLayer dragLayer = mLauncher.getDragLayer(); - // Just verify that the folder hasn't already been added to the DragLayer. - // There was a one-off crash where the folder had a parent already. - if (getParent() == null) { - dragLayer.addView(this); - mDragController.addDropTarget(this); - } else { - if (ProviderConfig.IS_DOGFOOD_BUILD) { - Log.e(TAG, "Opening folder (" + this + ") which already has a parent:" - + getParent()); + a.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animation) { + mState = STATE_ANIMATING; + mCurrentAnimator = a; } - } - - mIsOpen = true; - mContent.completePendingPageChanges(); - if (!mDragInProgress) { - // Open on the first page. - mContent.snapToPageImmediately(0); - } - - // This is set to true in close(), but isn't reset to false until onDropCompleted(). This - // leads to an inconsistent state if you drag out of the folder and drag back in without - // dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice. - mDeleteFolderOnDropCompleted = false; + @Override + public void onAnimationEnd(Animator animation) { + mCurrentAnimator = null; + } + }); + a.start(); + } - final Runnable onCompleteRunnable; + private AnimatorSet getOpeningAnimator() { prepareReveal(); - centerAboutIcon(); - mFolderIcon.growAndFadeOut(); AnimatorSet anim = LauncherAnimUtils.createAnimatorSet(); + int width = getFolderWidth(); int height = getFolderHeight(); @@ -587,24 +571,75 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC anim.play(textAlpha); anim.play(reveal); - mContent.setLayerType(LAYER_TYPE_HARDWARE, null); - mFooter.setLayerType(LAYER_TYPE_HARDWARE, null); + AnimationLayerSet layerSet = new AnimationLayerSet(); + layerSet.addView(mContent); + layerSet.addView(mFooter); + anim.addListener(layerSet); + + return anim; + } + + /** + * Opens the user folder described by the specified tag. The opening of the folder + * is animated relative to the specified View. If the View is null, no animation + * is played. + */ + public void animateOpen() { + Folder openFolder = getOpen(mLauncher); + if (openFolder != null && openFolder != this) { + // Close any open folder before opening a folder. + openFolder.close(true); + } + + DragLayer dragLayer = mLauncher.getDragLayer(); + // Just verify that the folder hasn't already been added to the DragLayer. + // There was a one-off crash where the folder had a parent already. + if (getParent() == null) { + dragLayer.addView(this); + mDragController.addDropTarget(this); + } else { + if (FeatureFlags.IS_DOGFOOD_BUILD) { + Log.e(TAG, "Opening folder (" + this + ") which already has a parent:" + + getParent()); + } + } + + mIsOpen = true; + + mContent.completePendingPageChanges(); + if (!mDragInProgress) { + // Open on the first page. + mContent.snapToPageImmediately(0); + } + + // This is set to true in close(), but isn't reset to false until onDropCompleted(). This + // leads to an inconsistent state if you drag out of the folder and drag back in without + // dropping. One resulting issue is that replaceFolderWithFinalItem() can be called twice. + mDeleteFolderOnDropCompleted = false; + + final Runnable onCompleteRunnable; + centerAboutIcon(); + + AnimatorSet anim = FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION + ? new FolderAnimationManager(this, true /* isOpening */).getAnimator() + : getOpeningAnimator(); onCompleteRunnable = new Runnable() { @Override public void run() { - mContent.setLayerType(LAYER_TYPE_NONE, null); - mFooter.setLayerType(LAYER_TYPE_NONE, null); mLauncher.getUserEventDispatcher().resetElapsedContainerMillis(); } }; anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { + if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) { + mFolderIcon.setVisibility(INVISIBLE); + } + Utilities.sendCustomAccessibilityEvent( Folder.this, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, mContent.getAccessibilityDescription()); - mState = STATE_ANIMATING; } @Override public void onAnimationEnd(Animator animation) { @@ -650,7 +685,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC } mPageIndicator.stopAllAnimations(); - anim.start(); + startAnimation(anim); // Make sure the folder picks up the last drag move even if the finger doesn't move. if (mDragController.isDragging()) { @@ -688,7 +723,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC mFolderName.dispatchBackKey(); } - if (mFolderIcon != null) { + if (mFolderIcon != null && !FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) { mFolderIcon.shrinkAndFadeIn(animate); } @@ -706,12 +741,24 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC parent.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED); } + private AnimatorSet getClosingAnimator() { + AnimatorSet animatorSet = LauncherAnimUtils.createAnimatorSet(); + animatorSet.play(LauncherAnimUtils.ofViewAlphaAndScale(this, 0, 0.9f, 0.9f)); + + AnimationLayerSet layerSet = new AnimationLayerSet(); + layerSet.addView(this); + animatorSet.addListener(layerSet); + animatorSet.setDuration(mExpandDuration); + return animatorSet; + } + private void animateClosed() { - final ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(this, 0, 0.9f, 0.9f); - oa.addListener(new AnimatorListenerAdapter() { + AnimatorSet a = FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION + ? new FolderAnimationManager(this, false /* isOpening */).getAnimator() + : getClosingAnimator(); + a.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - setLayerType(LAYER_TYPE_NONE, null); closeComplete(true); } @Override @@ -720,12 +767,9 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC Folder.this, AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED, getContext().getString(R.string.folder_closed)); - mState = STATE_ANIMATING; } }); - oa.setDuration(mExpandDuration); - setLayerType(LAYER_TYPE_HARDWARE, null); - oa.start(); + startAnimation(a); } private void closeComplete(boolean wasAnimated) { @@ -736,10 +780,15 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC } mDragController.removeDropTarget(this); clearFocus(); - if (wasAnimated) { - mFolderIcon.requestFocus(); + if (mFolderIcon != null) { + mFolderIcon.setVisibility(View.VISIBLE); + if (wasAnimated) { + mFolderIcon.mBackground.animateBackgroundStroke(); + mFolderIcon.requestFocus(); + } } + if (mRearrangeOnClose) { rearrangeChildren(); mRearrangeOnClose = false; @@ -1027,6 +1076,9 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC } public boolean isDropEnabled() { + if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) { + return mState != STATE_ANIMATING; + } return true; } @@ -1427,6 +1479,26 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC return mItemsInReadingOrder; } + public List<BubbleTextView> getItemsOnCurrentPage() { + ArrayList<View> allItems = getItemsInReadingOrder(); + int currentPage = mContent.getCurrentPage(); + int lastPage = mContent.getPageCount() - 1; + int totalItemsInFolder = allItems.size(); + int itemsPerPage = mContent.itemsPerPage(); + int numItemsOnCurrentPage = currentPage == lastPage + ? totalItemsInFolder - (itemsPerPage * currentPage) + : itemsPerPage; + + int startIndex = currentPage * itemsPerPage; + int endIndex = startIndex + numItemsOnCurrentPage; + + List<BubbleTextView> itemsOnCurrentPage = new ArrayList<>(numItemsOnCurrentPage); + for (int i = startIndex; i < endIndex; ++i) { + itemsOnCurrentPage.add((BubbleTextView) allItems.get(i)); + } + return itemsOnCurrentPage; + } + public void onFocusChange(View v, boolean hasFocus) { if (v == mFolderName) { if (hasFocus) { |