2017-03-03 14:57:14 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright (C) 2017 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.folder;
|
|
|
|
|
|
2018-04-13 11:41:50 -07:00
|
|
|
import static com.android.launcher3.BubbleTextView.TEXT_ALPHA_PROPERTY;
|
2017-10-16 11:46:41 -07:00
|
|
|
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
|
|
|
|
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
|
|
|
|
|
|
2017-03-03 14:57:14 -08:00
|
|
|
import android.animation.Animator;
|
|
|
|
|
import android.animation.AnimatorListenerAdapter;
|
|
|
|
|
import android.animation.AnimatorSet;
|
|
|
|
|
import android.animation.ObjectAnimator;
|
|
|
|
|
import android.animation.TimeInterpolator;
|
|
|
|
|
import android.content.Context;
|
2017-09-08 11:59:05 -07:00
|
|
|
import android.content.res.Resources;
|
2017-03-03 14:57:14 -08:00
|
|
|
import android.graphics.Color;
|
|
|
|
|
import android.graphics.Rect;
|
|
|
|
|
import android.graphics.drawable.GradientDrawable;
|
|
|
|
|
import android.support.v4.graphics.ColorUtils;
|
|
|
|
|
import android.util.Property;
|
|
|
|
|
import android.view.View;
|
|
|
|
|
import android.view.animation.AnimationUtils;
|
|
|
|
|
|
|
|
|
|
import com.android.launcher3.BubbleTextView;
|
|
|
|
|
import com.android.launcher3.CellLayout;
|
|
|
|
|
import com.android.launcher3.Launcher;
|
|
|
|
|
import com.android.launcher3.LauncherAnimUtils;
|
|
|
|
|
import com.android.launcher3.R;
|
|
|
|
|
import com.android.launcher3.ShortcutAndWidgetContainer;
|
|
|
|
|
import com.android.launcher3.Utilities;
|
2017-06-23 09:34:06 -07:00
|
|
|
import com.android.launcher3.anim.PropertyResetListener;
|
2017-03-03 14:57:14 -08:00
|
|
|
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
|
|
|
|
|
import com.android.launcher3.dragndrop.DragLayer;
|
|
|
|
|
import com.android.launcher3.util.Themes;
|
|
|
|
|
|
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Manages the opening and closing animations for a {@link Folder}.
|
|
|
|
|
*
|
|
|
|
|
* All of the animations are done in the Folder.
|
|
|
|
|
* ie. When the user taps on the FolderIcon, we immediately hide the FolderIcon and show the Folder
|
|
|
|
|
* in its place before starting the animation.
|
|
|
|
|
*/
|
|
|
|
|
public class FolderAnimationManager {
|
|
|
|
|
|
|
|
|
|
private Folder mFolder;
|
|
|
|
|
private FolderPagedView mContent;
|
|
|
|
|
private GradientDrawable mFolderBackground;
|
|
|
|
|
|
|
|
|
|
private FolderIcon mFolderIcon;
|
2017-06-22 18:34:45 -07:00
|
|
|
private PreviewBackground mPreviewBackground;
|
2017-03-03 14:57:14 -08:00
|
|
|
|
|
|
|
|
private Context mContext;
|
|
|
|
|
private Launcher mLauncher;
|
|
|
|
|
|
2017-03-14 14:12:19 -07:00
|
|
|
private final boolean mIsOpening;
|
|
|
|
|
|
2017-03-23 10:17:55 -07:00
|
|
|
private final int mDuration;
|
|
|
|
|
private final int mDelay;
|
|
|
|
|
|
2017-03-29 13:35:29 -07:00
|
|
|
private final TimeInterpolator mFolderInterpolator;
|
2017-06-29 09:20:20 -07:00
|
|
|
private final TimeInterpolator mLargeFolderPreviewItemOpenInterpolator;
|
|
|
|
|
private final TimeInterpolator mLargeFolderPreviewItemCloseInterpolator;
|
2017-03-03 14:57:14 -08:00
|
|
|
|
2017-06-23 18:40:31 -07:00
|
|
|
private final PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
|
2017-03-03 14:57:14 -08:00
|
|
|
|
|
|
|
|
|
2017-03-14 14:12:19 -07:00
|
|
|
public FolderAnimationManager(Folder folder, boolean isOpening) {
|
2017-03-03 14:57:14 -08:00
|
|
|
mFolder = folder;
|
|
|
|
|
mContent = folder.mContent;
|
|
|
|
|
mFolderBackground = (GradientDrawable) mFolder.getBackground();
|
|
|
|
|
|
|
|
|
|
mFolderIcon = folder.mFolderIcon;
|
|
|
|
|
mPreviewBackground = mFolderIcon.mBackground;
|
|
|
|
|
|
|
|
|
|
mContext = folder.getContext();
|
|
|
|
|
mLauncher = folder.mLauncher;
|
|
|
|
|
|
2017-03-14 14:12:19 -07:00
|
|
|
mIsOpening = isOpening;
|
|
|
|
|
|
2017-09-08 11:59:05 -07:00
|
|
|
Resources res = mContent.getResources();
|
|
|
|
|
mDuration = res.getInteger(R.integer.config_materialFolderExpandDuration);
|
|
|
|
|
mDelay = res.getInteger(R.integer.config_folderDelay);
|
2017-03-23 10:17:55 -07:00
|
|
|
|
2017-03-29 13:35:29 -07:00
|
|
|
mFolderInterpolator = AnimationUtils.loadInterpolator(mContext,
|
|
|
|
|
R.interpolator.folder_interpolator);
|
2017-06-29 09:20:20 -07:00
|
|
|
mLargeFolderPreviewItemOpenInterpolator = AnimationUtils.loadInterpolator(mContext,
|
|
|
|
|
R.interpolator.large_folder_preview_item_open_interpolator);
|
|
|
|
|
mLargeFolderPreviewItemCloseInterpolator = AnimationUtils.loadInterpolator(mContext,
|
|
|
|
|
R.interpolator.large_folder_preview_item_close_interpolator);
|
2017-03-03 14:57:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Prepares the Folder for animating between open / closed states.
|
|
|
|
|
*/
|
2017-03-14 14:12:19 -07:00
|
|
|
public AnimatorSet getAnimator() {
|
2017-03-03 14:57:14 -08:00
|
|
|
final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) mFolder.getLayoutParams();
|
2017-09-08 11:59:05 -07:00
|
|
|
ClippedFolderIconLayoutRule rule = mFolderIcon.getLayoutRule();
|
2017-07-06 16:31:56 -07:00
|
|
|
final List<BubbleTextView> itemsInPreview = mFolderIcon.getPreviewItems();
|
2017-03-03 14:57:14 -08:00
|
|
|
|
2017-03-29 13:35:29 -07:00
|
|
|
// Match position of the FolderIcon
|
|
|
|
|
final Rect folderIconPos = new Rect();
|
|
|
|
|
float scaleRelativeToDragLayer = mLauncher.getDragLayer()
|
|
|
|
|
.getDescendantRectRelativeToSelf(mFolderIcon, folderIconPos);
|
2017-07-14 12:42:22 -07:00
|
|
|
int scaledRadius = mPreviewBackground.getScaledRadius();
|
|
|
|
|
float initialSize = (scaledRadius * 2) * scaleRelativeToDragLayer;
|
2017-03-29 13:35:29 -07:00
|
|
|
|
2017-03-03 14:57:14 -08:00
|
|
|
// Match size/scale of icons in the preview
|
2017-09-08 11:59:05 -07:00
|
|
|
float previewScale = rule.scaleForItem(itemsInPreview.size());
|
2017-03-03 14:57:14 -08:00
|
|
|
float previewSize = rule.getIconSize() * previewScale;
|
2017-07-26 17:41:02 +00:00
|
|
|
float initialScale = previewSize / itemsInPreview.get(0).getIconSize()
|
2017-03-29 13:35:29 -07:00
|
|
|
* scaleRelativeToDragLayer;
|
2017-03-03 14:57:14 -08:00
|
|
|
final float finalScale = 1f;
|
2017-03-14 14:12:19 -07:00
|
|
|
float scale = mIsOpening ? initialScale : finalScale;
|
2017-03-03 14:57:14 -08:00
|
|
|
mFolder.setScaleX(scale);
|
|
|
|
|
mFolder.setScaleY(scale);
|
2017-03-14 14:12:19 -07:00
|
|
|
mFolder.setPivotX(0);
|
|
|
|
|
mFolder.setPivotY(0);
|
2017-03-03 14:57:14 -08:00
|
|
|
|
|
|
|
|
// 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.
|
2017-03-29 13:35:29 -07:00
|
|
|
int previewItemOffsetX = (int) (previewSize / 2);
|
2017-05-08 18:08:38 -07:00
|
|
|
if (Utilities.isRtl(mContext.getResources())) {
|
|
|
|
|
previewItemOffsetX = (int) (lp.width * initialScale - initialSize - previewItemOffsetX);
|
|
|
|
|
}
|
2017-03-03 14:57:14 -08:00
|
|
|
|
|
|
|
|
final int paddingOffsetX = (int) ((mFolder.getPaddingLeft() + mContent.getPaddingLeft())
|
2017-03-29 13:35:29 -07:00
|
|
|
* initialScale);
|
2017-07-26 17:41:02 +00:00
|
|
|
final int paddingOffsetY = (int) ((mFolder.getPaddingTop() + mContent.getPaddingTop())
|
|
|
|
|
* initialScale);
|
2017-03-29 13:35:29 -07:00
|
|
|
|
2017-06-29 09:20:20 -07:00
|
|
|
int initialX = folderIconPos.left + mPreviewBackground.getOffsetX() - paddingOffsetX
|
2017-07-14 12:42:22 -07:00
|
|
|
- previewItemOffsetX;
|
|
|
|
|
int initialY = folderIconPos.top + mPreviewBackground.getOffsetY() - paddingOffsetY;
|
2017-03-03 14:57:14 -08:00
|
|
|
final float xDistance = initialX - lp.x;
|
|
|
|
|
final float yDistance = initialY - lp.y;
|
|
|
|
|
|
|
|
|
|
// Set up the Folder background.
|
|
|
|
|
final int finalColor = Themes.getAttrColor(mContext, android.R.attr.colorPrimary);
|
|
|
|
|
final int initialColor =
|
|
|
|
|
ColorUtils.setAlphaComponent(finalColor, mPreviewBackground.getBackgroundAlpha());
|
2017-03-14 14:12:19 -07:00
|
|
|
mFolderBackground.setColor(mIsOpening ? initialColor : finalColor);
|
2017-03-03 14:57:14 -08:00
|
|
|
|
|
|
|
|
// Set up the reveal animation that clips the Folder.
|
2017-03-29 13:35:29 -07:00
|
|
|
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));
|
2017-03-03 14:57:14 -08:00
|
|
|
Rect endRect = new Rect(0, 0, lp.width, lp.height);
|
2017-03-29 13:35:29 -07:00
|
|
|
float initialRadius = initialSize / initialScale / 2f;
|
2017-03-14 14:12:19 -07:00
|
|
|
float finalRadius = Utilities.pxFromDp(2, mContext.getResources().getDisplayMetrics());
|
|
|
|
|
|
|
|
|
|
// Create the animators.
|
|
|
|
|
AnimatorSet a = LauncherAnimUtils.createAnimatorSet();
|
2017-03-23 10:17:55 -07:00
|
|
|
|
2017-06-23 09:34:06 -07:00
|
|
|
// Initialize the Folder items' text.
|
2018-04-13 11:41:50 -07:00
|
|
|
PropertyResetListener colorResetListener =
|
|
|
|
|
new PropertyResetListener<>(TEXT_ALPHA_PROPERTY, 1f);
|
2017-07-06 16:31:56 -07:00
|
|
|
for (BubbleTextView icon : mFolder.getItemsOnPage(mFolder.mContent.getCurrentPage())) {
|
2017-06-23 09:34:06 -07:00
|
|
|
if (mIsOpening) {
|
|
|
|
|
icon.setTextVisibility(false);
|
|
|
|
|
}
|
|
|
|
|
ObjectAnimator anim = icon.createTextAlphaAnimator(mIsOpening);
|
|
|
|
|
anim.addListener(colorResetListener);
|
|
|
|
|
play(a, anim);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-23 10:17:55 -07:00
|
|
|
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(mFolderBackground, "color", initialColor, finalColor));
|
2017-06-18 17:43:16 -07:00
|
|
|
play(a, mFolderIcon.mFolderName.createTextAlphaAnimator(!mIsOpening));
|
2017-06-22 14:22:40 -07:00
|
|
|
RoundedRectRevealOutlineProvider outlineProvider = new RoundedRectRevealOutlineProvider(
|
|
|
|
|
initialRadius, finalRadius, startRect, endRect) {
|
|
|
|
|
@Override
|
|
|
|
|
public boolean shouldRemoveElevationDuringAnimation() {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
play(a, outlineProvider.createRevealAnimator(mFolder, !mIsOpening));
|
2017-03-03 14:57:14 -08:00
|
|
|
|
2017-06-26 11:24:33 -07:00
|
|
|
// 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);
|
2017-06-29 09:20:20 -07:00
|
|
|
play(a, z, mIsOpening ? midDuration : 0, midDuration);
|
2017-06-26 11:24:33 -07:00
|
|
|
|
2017-03-07 08:03:40 -08:00
|
|
|
a.addListener(new AnimatorListenerAdapter() {
|
|
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
|
|
|
|
super.onAnimationEnd(animation);
|
2017-03-14 14:12:19 -07:00
|
|
|
mFolder.setTranslationX(0.0f);
|
|
|
|
|
mFolder.setTranslationY(0.0f);
|
2017-06-26 11:24:33 -07:00
|
|
|
mFolder.setTranslationZ(0.0f);
|
2017-03-14 14:12:19 -07:00
|
|
|
mFolder.setScaleX(1f);
|
|
|
|
|
mFolder.setScaleY(1f);
|
2017-03-07 08:03:40 -08:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2017-03-08 12:22:34 -08:00
|
|
|
// We set the interpolator on all current child animators here, because the preview item
|
|
|
|
|
// animators may use a different interpolator.
|
|
|
|
|
for (Animator animator : a.getChildAnimations()) {
|
2017-03-29 13:35:29 -07:00
|
|
|
animator.setInterpolator(mFolderInterpolator);
|
2017-03-08 12:22:34 -08:00
|
|
|
}
|
|
|
|
|
|
2017-07-14 12:42:22 -07:00
|
|
|
int radiusDiff = scaledRadius - mPreviewBackground.getRadius();
|
|
|
|
|
addPreviewItemAnimators(a, initialScale / scaleRelativeToDragLayer,
|
|
|
|
|
// Background can have a scaled radius in drag and drop mode, so we need to add the
|
|
|
|
|
// difference to keep the preview items centered.
|
|
|
|
|
previewItemOffsetX + radiusDiff, radiusDiff);
|
2017-03-03 14:57:14 -08:00
|
|
|
return a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2017-07-06 16:31:56 -07:00
|
|
|
* Animate the items on the current page.
|
2017-03-03 14:57:14 -08:00
|
|
|
*/
|
2017-03-29 13:35:29 -07:00
|
|
|
private void addPreviewItemAnimators(AnimatorSet animatorSet, final float folderScale,
|
2017-07-14 12:42:22 -07:00
|
|
|
int previewItemOffsetX, int previewItemOffsetY) {
|
2017-09-08 11:59:05 -07:00
|
|
|
ClippedFolderIconLayoutRule rule = mFolderIcon.getLayoutRule();
|
2017-07-06 16:31:56 -07:00
|
|
|
boolean isOnFirstPage = mFolder.mContent.getCurrentPage() == 0;
|
|
|
|
|
final List<BubbleTextView> itemsInPreview = isOnFirstPage
|
|
|
|
|
? mFolderIcon.getPreviewItems()
|
|
|
|
|
: mFolderIcon.getPreviewItemsOnPage(mFolder.mContent.getCurrentPage());
|
2017-03-03 14:57:14 -08:00
|
|
|
final int numItemsInPreview = itemsInPreview.size();
|
2017-07-06 16:31:56 -07:00
|
|
|
final int numItemsInFirstPagePreview = isOnFirstPage
|
2017-09-08 11:59:05 -07:00
|
|
|
? numItemsInPreview : MAX_NUM_ITEMS_IN_PREVIEW;
|
2017-03-03 14:57:14 -08:00
|
|
|
|
2017-03-14 14:12:19 -07:00
|
|
|
TimeInterpolator previewItemInterpolator = getPreviewItemInterpolator();
|
2017-03-08 12:22:34 -08:00
|
|
|
|
2017-03-03 14:57:14 -08:00
|
|
|
ShortcutAndWidgetContainer cwc = mContent.getPageAt(0).getShortcutsAndWidgets();
|
|
|
|
|
for (int i = 0; i < numItemsInPreview; ++i) {
|
|
|
|
|
final BubbleTextView btv = itemsInPreview.get(i);
|
|
|
|
|
CellLayout.LayoutParams btvLp = (CellLayout.LayoutParams) btv.getLayoutParams();
|
|
|
|
|
|
|
|
|
|
// Calculate the final values in the LayoutParams.
|
|
|
|
|
btvLp.isLockedToGrid = true;
|
|
|
|
|
cwc.setupLp(btv);
|
|
|
|
|
|
2017-07-06 16:31:56 -07:00
|
|
|
// Match scale of icons in the preview of the items on the first page.
|
2017-09-08 11:59:05 -07:00
|
|
|
float previewScale = rule.scaleForItem(numItemsInFirstPagePreview);
|
2017-03-03 14:57:14 -08:00
|
|
|
float previewSize = rule.getIconSize() * previewScale;
|
|
|
|
|
float iconScale = previewSize / itemsInPreview.get(i).getIconSize();
|
|
|
|
|
|
|
|
|
|
final float initialScale = iconScale / folderScale;
|
|
|
|
|
final float finalScale = 1f;
|
2017-03-14 14:12:19 -07:00
|
|
|
float scale = mIsOpening ? initialScale : finalScale;
|
2017-03-03 14:57:14 -08:00
|
|
|
btv.setScaleX(scale);
|
|
|
|
|
btv.setScaleY(scale);
|
|
|
|
|
|
|
|
|
|
// Match positions of the icons in the folder with their positions in the preview
|
2017-07-06 16:31:56 -07:00
|
|
|
rule.computePreviewItemDrawingParams(i, numItemsInFirstPagePreview, mTmpParams);
|
2017-03-03 14:57:14 -08:00
|
|
|
// The PreviewLayoutRule assumes that the icon size takes up the entire width so we
|
|
|
|
|
// offset by the actual size.
|
|
|
|
|
int iconOffsetX = (int) ((btvLp.width - btv.getIconSize()) * iconScale) / 2;
|
|
|
|
|
|
|
|
|
|
final int previewPosX =
|
2017-03-29 13:35:29 -07:00
|
|
|
(int) ((mTmpParams.transX - iconOffsetX + previewItemOffsetX) / folderScale);
|
2017-07-14 12:42:22 -07:00
|
|
|
final int previewPosY = (int) ((mTmpParams.transY + previewItemOffsetY) / folderScale);
|
2017-03-03 14:57:14 -08:00
|
|
|
|
|
|
|
|
final float xDistance = previewPosX - btvLp.x;
|
|
|
|
|
final float yDistance = previewPosY - btvLp.y;
|
|
|
|
|
|
2017-03-14 14:12:19 -07:00
|
|
|
Animator translationX = getAnimator(btv, View.TRANSLATION_X, xDistance, 0f);
|
2017-03-08 12:22:34 -08:00
|
|
|
translationX.setInterpolator(previewItemInterpolator);
|
2017-03-23 10:17:55 -07:00
|
|
|
play(animatorSet, translationX);
|
2017-03-03 14:57:14 -08:00
|
|
|
|
2017-03-14 14:12:19 -07:00
|
|
|
Animator translationY = getAnimator(btv, View.TRANSLATION_Y, yDistance, 0f);
|
2017-03-08 12:22:34 -08:00
|
|
|
translationY.setInterpolator(previewItemInterpolator);
|
2017-03-23 10:17:55 -07:00
|
|
|
play(animatorSet, translationY);
|
2017-03-03 14:57:14 -08:00
|
|
|
|
2017-03-14 14:12:19 -07:00
|
|
|
Animator scaleAnimator = getAnimator(btv, SCALE_PROPERTY, initialScale, finalScale);
|
2017-03-08 12:22:34 -08:00
|
|
|
scaleAnimator.setInterpolator(previewItemInterpolator);
|
2017-03-23 10:17:55 -07:00
|
|
|
play(animatorSet, scaleAnimator);
|
|
|
|
|
|
2017-09-08 11:59:05 -07:00
|
|
|
if (mFolder.getItemCount() > MAX_NUM_ITEMS_IN_PREVIEW) {
|
2017-03-23 10:17:55 -07:00
|
|
|
// These delays allows the preview items to move as part of the Folder's motion,
|
|
|
|
|
// and its only necessary for large folders because of differing interpolators.
|
2017-06-29 09:20:20 -07:00
|
|
|
int delay = mIsOpening ? mDelay : mDelay * 2;
|
2017-03-23 10:17:55 -07:00
|
|
|
if (mIsOpening) {
|
2017-06-29 09:20:20 -07:00
|
|
|
translationX.setStartDelay(delay);
|
|
|
|
|
translationY.setStartDelay(delay);
|
|
|
|
|
scaleAnimator.setStartDelay(delay);
|
2017-03-23 10:17:55 -07:00
|
|
|
}
|
2017-06-29 09:20:20 -07:00
|
|
|
translationX.setDuration(translationX.getDuration() - delay);
|
|
|
|
|
translationY.setDuration(translationY.getDuration() - delay);
|
|
|
|
|
scaleAnimator.setDuration(scaleAnimator.getDuration() - delay);
|
2017-03-23 10:17:55 -07:00
|
|
|
}
|
2017-03-03 14:57:14 -08:00
|
|
|
|
|
|
|
|
animatorSet.addListener(new AnimatorListenerAdapter() {
|
2017-03-23 10:17:55 -07:00
|
|
|
@Override
|
|
|
|
|
public void onAnimationStart(Animator animation) {
|
|
|
|
|
super.onAnimationStart(animation);
|
|
|
|
|
// Necessary to initialize values here because of the start delay.
|
|
|
|
|
if (mIsOpening) {
|
|
|
|
|
btv.setTranslationX(xDistance);
|
|
|
|
|
btv.setTranslationY(yDistance);
|
|
|
|
|
btv.setScaleX(initialScale);
|
|
|
|
|
btv.setScaleY(initialScale);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-03 14:57:14 -08:00
|
|
|
@Override
|
|
|
|
|
public void onAnimationEnd(Animator animation) {
|
|
|
|
|
super.onAnimationEnd(animation);
|
|
|
|
|
btv.setTranslationX(0.0f);
|
|
|
|
|
btv.setTranslationY(0.0f);
|
|
|
|
|
btv.setScaleX(1f);
|
|
|
|
|
btv.setScaleY(1f);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-03-08 12:22:34 -08:00
|
|
|
|
2017-03-23 10:17:55 -07:00
|
|
|
private void play(AnimatorSet as, Animator a) {
|
2017-06-26 11:24:33 -07:00
|
|
|
play(as, a, a.getStartDelay(), mDuration);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void play(AnimatorSet as, Animator a, long startDelay, int duration) {
|
|
|
|
|
a.setStartDelay(startDelay);
|
|
|
|
|
a.setDuration(duration);
|
2017-03-23 10:17:55 -07:00
|
|
|
as.play(a);
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-14 14:12:19 -07:00
|
|
|
private TimeInterpolator getPreviewItemInterpolator() {
|
2017-09-08 11:59:05 -07:00
|
|
|
if (mFolder.getItemCount() > MAX_NUM_ITEMS_IN_PREVIEW) {
|
2017-03-08 12:22:34 -08:00
|
|
|
// With larger folders, we want the preview items to reach their final positions faster
|
|
|
|
|
// (when opening) and later (when closing) so that they appear aligned with the rest of
|
|
|
|
|
// the folder items when they are both visible.
|
2017-06-29 09:20:20 -07:00
|
|
|
return mIsOpening
|
|
|
|
|
? mLargeFolderPreviewItemOpenInterpolator
|
|
|
|
|
: mLargeFolderPreviewItemCloseInterpolator;
|
2017-03-08 12:22:34 -08:00
|
|
|
}
|
2017-03-29 13:35:29 -07:00
|
|
|
return mFolderInterpolator;
|
2017-03-14 14:12:19 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Animator getAnimator(View view, Property property, float v1, float v2) {
|
|
|
|
|
return mIsOpening
|
|
|
|
|
? ObjectAnimator.ofFloat(view, property, v1, v2)
|
|
|
|
|
: ObjectAnimator.ofFloat(view, property, v2, v1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private Animator getAnimator(GradientDrawable drawable, String property, int v1, int v2) {
|
|
|
|
|
return mIsOpening
|
|
|
|
|
? ObjectAnimator.ofArgb(drawable, property, v1, v2)
|
|
|
|
|
: ObjectAnimator.ofArgb(drawable, property, v2, v1);
|
2017-03-08 12:22:34 -08:00
|
|
|
}
|
2017-03-03 14:57:14 -08:00
|
|
|
}
|