Merge "Removing some folder customization options" into ub-launcher3-master

This commit is contained in:
TreeHugger Robot
2017-09-08 22:41:35 +00:00
committed by Android (Google) Code Review
11 changed files with 64 additions and 507 deletions

View File

@@ -86,9 +86,7 @@
<integer name="config_dropAnimMaxDuration">500</integer>
<!-- The duration of the UserFolder opening and closing animation -->
<integer name="config_folderExpandDuration">120</integer>
<integer name="config_materialFolderExpandDuration">200</integer>
<integer name="config_materialFolderExpandStagger">60</integer>
<integer name="config_folderDelay">30</integer>
<!-- The distance at which the animation should take the max duration -->
@@ -128,9 +126,6 @@
<!-- View ID used by cell layout to jail its content -->
<item type="id" name="cell_layout_jail_id" />
<!-- View ID used by PreviewImageView to cache its instance -->
<item type="id" name="preview_image_id" />
<!-- Popup items -->
<integer name="config_popupOpenCloseDuration">150</integer>
<integer name="config_popupArrowOpenDuration">80</integer>

View File

@@ -32,9 +32,7 @@ abstract class BaseFlags {
// Custom flags go below this
public static boolean LAUNCHER3_DISABLE_ICON_NORMALIZATION = false;
public static boolean LAUNCHER3_LEGACY_FOLDER_ICON = false;
public static boolean LAUNCHER3_DISABLE_PINCH_TO_OVERVIEW = false;
public static boolean LAUNCHER3_NEW_FOLDER_ANIMATION = true;
// When enabled allows to use any point on the fast scrollbar to start dragging.
public static final boolean LAUNCHER3_DIRECT_SCROLL = true;
// When enabled while all-apps open, the soft input will be set to adjust resize .

View File

@@ -1,9 +1,8 @@
package com.android.launcher3.folder;
public class ClippedFolderIconLayoutRule {
public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule {
static final int MAX_NUM_ITEMS_IN_PREVIEW = 4;
public static final int MAX_NUM_ITEMS_IN_PREVIEW = 4;
private static final int MIN_NUM_ITEMS_IN_PREVIEW = 2;
private static final float MIN_SCALE = 0.48f;
@@ -11,8 +10,8 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
private static final float MAX_RADIUS_DILATION = 0.15f;
private static final float ITEM_RADIUS_SCALE_FACTOR = 1.33f;
private static final int EXIT_INDEX = -2;
private static final int ENTER_INDEX = -3;
public static final int EXIT_INDEX = -2;
public static final int ENTER_INDEX = -3;
private float[] mTmpPoint = new float[2];
@@ -22,7 +21,6 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
private boolean mIsRtl;
private float mBaselineIconScale;
@Override
public void init(int availableSpace, float intrinsicIconSize, boolean rtl) {
mAvailableSpace = availableSpace;
mRadius = ITEM_RADIUS_SCALE_FACTOR * availableSpace / 2f;
@@ -31,19 +29,18 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
mBaselineIconScale = availableSpace / (intrinsicIconSize * 1f);
}
@Override
public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
PreviewItemDrawingParams params) {
float totalScale = scaleForItem(index, curNumItems);
float totalScale = scaleForItem(curNumItems);
float transX;
float transY;
float overlayAlpha = 0;
if (index == getExitIndex()) {
if (index == EXIT_INDEX) {
// 0 1 * <-- Exit position (row 0, col 2)
// 2 3
getGridPosition(0, 2, mTmpPoint);
} else if (index == getEnterIndex()) {
} else if (index == ENTER_INDEX) {
// 0 1
// 2 3 * <-- Enter position (row 1, col 2)
getGridPosition(1, 2, mTmpPoint);
@@ -120,7 +117,7 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
MIN_NUM_ITEMS_IN_PREVIEW) / (MAX_NUM_ITEMS_IN_PREVIEW - MIN_NUM_ITEMS_IN_PREVIEW));
double theta = theta0 + index * (2 * Math.PI / curNumItems) * direction;
float halfIconSize = (mIconSize * scaleForItem(index, curNumItems)) / 2;
float halfIconSize = (mIconSize * scaleForItem(curNumItems)) / 2;
// Map the location along the circle, and offset the coordinates to represent the center
// of the icon, and to be based from the top / left of the preview area. The y component
@@ -130,10 +127,9 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
}
@Override
public float scaleForItem(int index, int numItems) {
public float scaleForItem(int numItems) {
// Scale is determined by the number of items in the preview.
float scale = 1f;
final float scale;
if (numItems <= 2) {
scale = MAX_SCALE;
} else if (numItems == 3) {
@@ -141,37 +137,10 @@ public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule
} else {
scale = MIN_SCALE;
}
return scale * mBaselineIconScale;
}
@Override
public float getIconSize() {
return mIconSize;
}
@Override
public int maxNumItems() {
return MAX_NUM_ITEMS_IN_PREVIEW;
}
@Override
public boolean clipToBackground() {
return true;
}
@Override
public boolean hasEnterExitIndices() {
return true;
}
@Override
public int getExitIndex() {
return EXIT_INDEX;
}
@Override
public int getEnterIndex() {
return ENTER_INDEX;
}
}

View File

@@ -19,8 +19,6 @@ package com.android.launcher3.folder;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
@@ -37,7 +35,6 @@ import android.view.MenuItem;
import android.view.View;
import android.view.ViewDebug;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
@@ -55,9 +52,7 @@ import com.android.launcher3.FolderInfo;
import com.android.launcher3.FolderInfo.FolderListener;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.LogDecelerateInterpolator;
import com.android.launcher3.OnAlarmListener;
import com.android.launcher3.PagedView;
import com.android.launcher3.R;
@@ -66,8 +61,6 @@ 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.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragController.DragListener;
@@ -137,10 +130,6 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
private AnimatorSet mCurrentAnimator;
private final int mExpandDuration;
public final int mMaterialExpandDuration;
private final int mMaterialExpandStagger;
protected final Launcher mLauncher;
protected DragController mDragController;
public FolderInfo mInfo;
@@ -201,9 +190,6 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
super(context, attrs);
setAlwaysDrawnWithCacheEnabled(false);
Resources res = getResources();
mExpandDuration = res.getInteger(R.integer.config_folderExpandDuration);
mMaterialExpandDuration = res.getInteger(R.integer.config_materialFolderExpandDuration);
mMaterialExpandStagger = res.getInteger(R.integer.config_materialFolderExpandStagger);
if (sDefaultFolderName == null) {
sDefaultFolderName = res.getString(R.string.folder_name);
@@ -487,25 +473,6 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
? R.layout.user_folder : R.layout.user_folder_icon_normalized, null);
}
/**
* This method is intended to make the UserFolder to be visually identical in size and position
* to its associated FolderIcon. This allows for a seamless transition into the expanded state.
*/
private void positionAndSizeAsIcon() {
if (!(getParent() instanceof DragLayer)) return;
setScaleX(0.8f);
setScaleY(0.8f);
setAlpha(0f);
mState = STATE_SMALL;
}
private void prepareReveal() {
setScaleX(1f);
setScaleY(1f);
setAlpha(1f);
mState = STATE_SMALL;
}
private void startAnimation(final AnimatorSet a) {
if (mCurrentAnimator != null && mCurrentAnimator.isRunning()) {
mCurrentAnimator.cancel();
@@ -525,61 +492,6 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
a.start();
}
private AnimatorSet getOpeningAnimator() {
prepareReveal();
mFolderIcon.growAndFadeOut();
AnimatorSet anim = LauncherAnimUtils.createAnimatorSet();
int width = getFolderWidth();
int height = getFolderHeight();
float transX = - 0.075f * (width / 2 - getPivotX());
float transY = - 0.075f * (height / 2 - getPivotY());
setTranslationX(transX);
setTranslationY(transY);
PropertyValuesHolder tx = PropertyValuesHolder.ofFloat(TRANSLATION_X, transX, 0);
PropertyValuesHolder ty = PropertyValuesHolder.ofFloat(TRANSLATION_Y, transY, 0);
Animator drift = ObjectAnimator.ofPropertyValuesHolder(this, tx, ty);
drift.setDuration(mMaterialExpandDuration);
drift.setStartDelay(mMaterialExpandStagger);
drift.setInterpolator(new LogDecelerateInterpolator(100, 0));
int rx = (int) Math.max(Math.max(width - getPivotX(), 0), getPivotX());
int ry = (int) Math.max(Math.max(height - getPivotY(), 0), getPivotY());
float radius = (float) Math.hypot(rx, ry);
Animator reveal = new CircleRevealOutlineProvider((int) getPivotX(),
(int) getPivotY(), 0, radius).createRevealAnimator(this);
reveal.setDuration(mMaterialExpandDuration);
reveal.setInterpolator(new LogDecelerateInterpolator(100, 0));
mContent.setAlpha(0f);
Animator iconsAlpha = ObjectAnimator.ofFloat(mContent, "alpha", 0f, 1f);
iconsAlpha.setDuration(mMaterialExpandDuration);
iconsAlpha.setStartDelay(mMaterialExpandStagger);
iconsAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
mFooter.setAlpha(0f);
Animator textAlpha = ObjectAnimator.ofFloat(mFooter, "alpha", 0f, 1f);
textAlpha.setDuration(mMaterialExpandDuration);
textAlpha.setStartDelay(mMaterialExpandStagger);
textAlpha.setInterpolator(new AccelerateInterpolator(1.5f));
anim.play(drift);
anim.play(iconsAlpha);
anim.play(textAlpha);
anim.play(reveal);
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
@@ -621,9 +533,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
final Runnable onCompleteRunnable;
centerAboutIcon();
AnimatorSet anim = FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION
? new FolderAnimationManager(this, true /* isOpening */).getAnimator()
: getOpeningAnimator();
AnimatorSet anim = new FolderAnimationManager(this, true /* isOpening */).getAnimator();
onCompleteRunnable = new Runnable() {
@Override
public void run() {
@@ -633,12 +543,8 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) {
mFolderIcon.setBackgroundVisible(false);
mFolderIcon.drawLeaveBehindIfExists();
} else {
mFolderIcon.setVisibility(INVISIBLE);
}
mFolderIcon.setBackgroundVisible(false);
mFolderIcon.drawLeaveBehindIfExists();
Utilities.sendCustomAccessibilityEvent(
Folder.this,
@@ -728,11 +634,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
}
if (mFolderIcon != null) {
if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) {
mFolderIcon.clearLeaveBehindIfExists();
} else {
mFolderIcon.shrinkAndFadeIn(animate);
}
mFolderIcon.clearLeaveBehindIfExists();
}
if (!(getParent() instanceof DragLayer)) return;
@@ -749,21 +651,8 @@ 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() {
AnimatorSet a = FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION
? new FolderAnimationManager(this, false /* isOpening */).getAnimator()
: getClosingAnimator();
AnimatorSet a = new FolderAnimationManager(this, false /* isOpening */).getAnimator();
a.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -790,16 +679,12 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
clearFocus();
if (mFolderIcon != null) {
mFolderIcon.setVisibility(View.VISIBLE);
if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) {
mFolderIcon.setBackgroundVisible(true);
mFolderIcon.mFolderName.setTextVisibility(true);
}
mFolderIcon.setBackgroundVisible(true);
mFolderIcon.mFolderName.setTextVisibility(true);
if (wasAnimated) {
if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) {
mFolderIcon.mBackground.fadeInBackgroundShadow();
mFolderIcon.mBackground.animateBackgroundStroke();
mFolderIcon.onFolderClose(mContent.getCurrentPage());
}
mFolderIcon.mBackground.fadeInBackgroundShadow();
mFolderIcon.mBackground.animateBackgroundStroke();
mFolderIcon.onFolderClose(mContent.getCurrentPage());
if (mFolderIcon.hasBadge()) {
mFolderIcon.createBadgeScaleAnimator(0f, 1f).start();
}
@@ -852,18 +737,14 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
return (getLayoutDirection() == LAYOUT_DIRECTION_RTL);
}
@Override
public void onDragOver(DragObject d) {
onDragOver(d, REORDER_DELAY);
}
private int getTargetRank(DragObject d, float[] recycle) {
recycle = d.getVisualCenter(recycle);
return mContent.findNearestArea(
(int) recycle[0] - getPaddingLeft(), (int) recycle[1] - getPaddingTop());
}
@Thunk void onDragOver(DragObject d, int reorderDelay) {
@Override
public void onDragOver(DragObject d) {
if (mScrollPauseAlarm.alarmPending()) {
return;
}
@@ -1095,10 +976,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
}
public boolean isDropEnabled() {
if (FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION) {
return mState != STATE_ANIMATING;
}
return true;
return mState != STATE_ANIMATING;
}
public boolean isFull() {
@@ -1113,7 +991,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
int width = getFolderWidth();
int height = getFolderHeight();
float scale = parent.getDescendantRectRelativeToSelf(mFolderIcon, sTempRect);
parent.getDescendantRectRelativeToSelf(mFolderIcon, sTempRect);
int centerX = sTempRect.centerX();
int centerY = sTempRect.centerY();
int centeredLeft = centerX - width / 2;
@@ -1611,7 +1489,7 @@ public class Folder extends AbstractFloatingView implements DragSource, View.OnC
@Override
public void onAlarm(Alarm alarm) {
// Reorder immediately on page change.
onDragOver(mDragObject, 1);
onDragOver(mDragObject);
}
}

View File

@@ -22,6 +22,7 @@ import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.GradientDrawable;
@@ -44,6 +45,8 @@ import com.android.launcher3.util.Themes;
import java.util.List;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
/**
* Manages the opening and closing animations for a {@link Folder}.
*
@@ -101,8 +104,9 @@ public class FolderAnimationManager {
mIsOpening = isOpening;
mDuration = mFolder.mMaterialExpandDuration;
mDelay = mContext.getResources().getInteger(R.integer.config_folderDelay);
Resources res = mContent.getResources();
mDuration = res.getInteger(R.integer.config_materialFolderExpandDuration);
mDelay = res.getInteger(R.integer.config_folderDelay);
mFolderInterpolator = AnimationUtils.loadInterpolator(mContext,
R.interpolator.folder_interpolator);
@@ -118,7 +122,7 @@ public class FolderAnimationManager {
*/
public AnimatorSet getAnimator() {
final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) mFolder.getLayoutParams();
FolderIcon.PreviewLayoutRule rule = mFolderIcon.getLayoutRule();
ClippedFolderIconLayoutRule rule = mFolderIcon.getLayoutRule();
final List<BubbleTextView> itemsInPreview = mFolderIcon.getPreviewItems();
// Match position of the FolderIcon
@@ -129,7 +133,7 @@ public class FolderAnimationManager {
float initialSize = (scaledRadius * 2) * scaleRelativeToDragLayer;
// Match size/scale of icons in the preview
float previewScale = rule.scaleForItem(0, itemsInPreview.size());
float previewScale = rule.scaleForItem(itemsInPreview.size());
float previewSize = rule.getIconSize() * previewScale;
float initialScale = previewSize / itemsInPreview.get(0).getIconSize()
* scaleRelativeToDragLayer;
@@ -242,15 +246,14 @@ public class FolderAnimationManager {
*/
private void addPreviewItemAnimators(AnimatorSet animatorSet, final float folderScale,
int previewItemOffsetX, int previewItemOffsetY) {
FolderIcon.PreviewLayoutRule rule = mFolderIcon.getLayoutRule();
ClippedFolderIconLayoutRule rule = mFolderIcon.getLayoutRule();
boolean isOnFirstPage = mFolder.mContent.getCurrentPage() == 0;
final List<BubbleTextView> itemsInPreview = isOnFirstPage
? mFolderIcon.getPreviewItems()
: mFolderIcon.getPreviewItemsOnPage(mFolder.mContent.getCurrentPage());
final int numItemsInPreview = itemsInPreview.size();
final int numItemsInFirstPagePreview = isOnFirstPage
? numItemsInPreview
: FolderIcon.NUM_ITEMS_IN_PREVIEW;
? numItemsInPreview : MAX_NUM_ITEMS_IN_PREVIEW;
TimeInterpolator previewItemInterpolator = getPreviewItemInterpolator();
@@ -264,7 +267,7 @@ public class FolderAnimationManager {
cwc.setupLp(btv);
// Match scale of icons in the preview of the items on the first page.
float previewScale = rule.scaleForItem(i, numItemsInFirstPagePreview);
float previewScale = rule.scaleForItem(numItemsInFirstPagePreview);
float previewSize = rule.getIconSize() * previewScale;
float iconScale = previewSize / itemsInPreview.get(i).getIconSize();
@@ -299,7 +302,7 @@ public class FolderAnimationManager {
scaleAnimator.setInterpolator(previewItemInterpolator);
play(animatorSet, scaleAnimator);
if (mFolder.getItemCount() > FolderIcon.NUM_ITEMS_IN_PREVIEW) {
if (mFolder.getItemCount() > MAX_NUM_ITEMS_IN_PREVIEW) {
// 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.
int delay = mIsOpening ? mDelay : mDelay * 2;
@@ -349,7 +352,7 @@ public class FolderAnimationManager {
}
private TimeInterpolator getPreviewItemInterpolator() {
if (mFolder.getItemCount() > FolderIcon.NUM_ITEMS_IN_PREVIEW) {
if (mFolder.getItemCount() > MAX_NUM_ITEMS_IN_PREVIEW) {
// 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.

View File

@@ -17,7 +17,6 @@
package com.android.launcher3.folder;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
@@ -49,7 +48,6 @@ import com.android.launcher3.FolderInfo;
import com.android.launcher3.FolderInfo.FolderListener;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.OnAlarmListener;
import com.android.launcher3.R;
@@ -60,7 +58,6 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.Workspace;
import com.android.launcher3.badge.BadgeRenderer;
import com.android.launcher3.badge.FolderBadgeInfo;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.BaseItemDragListener;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragView;
@@ -71,6 +68,7 @@ import com.android.launcher3.widget.PendingAddShortcutInfo;
import java.util.ArrayList;
import java.util.List;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
import static com.android.launcher3.folder.PreviewItemManager.INITIAL_ITEM_ANIMATION_DURATION;
/**
@@ -82,10 +80,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private FolderInfo mInfo;
@Thunk static boolean sStaticValuesDirty = true;
public static final int NUM_ITEMS_IN_PREVIEW = FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON ?
StackFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW :
ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
private CheckLongPressHelper mLongPressHelper;
private StylusEventHelper mStylusEventHelper;
@@ -103,7 +97,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private boolean mBackgroundIsVisible = true;
FolderIconPreviewVerifier mPreviewVerifier;
PreviewLayoutRule mPreviewLayoutRule;
ClippedFolderIconLayoutRule mPreviewLayoutRule;
private PreviewItemManager mPreviewItemManager;
private PreviewItemDrawingParams mTmpParams = new PreviewItemDrawingParams(0, 0, 0, 0);
@@ -146,9 +140,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private void init() {
mLongPressHelper = new CheckLongPressHelper(this);
mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this);
mPreviewLayoutRule = FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON ?
new StackFolderIconLayoutRule() :
new ClippedFolderIconLayoutRule();
mPreviewLayoutRule = new ClippedFolderIconLayoutRule();
mSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
mPreviewItemManager = new PreviewItemManager(this);
}
@@ -314,8 +306,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
boolean itemAdded = false;
if (index >= mPreviewLayoutRule.maxNumItems()
&& mPreviewLayoutRule.hasEnterExitIndices()) {
if (index >= MAX_NUM_ITEMS_IN_PREVIEW) {
List<BubbleTextView> oldPreviewItems = getPreviewItemsOnPage(0);
addItem(item, false);
List<BubbleTextView> newPreviewItems = getPreviewItemsOnPage(0);
@@ -347,7 +338,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
to.offset(center[0] - animateView.getMeasuredWidth() / 2,
center[1] - animateView.getMeasuredHeight() / 2);
float finalAlpha = index < mPreviewLayoutRule.maxNumItems() ? 0.5f : 0f;
float finalAlpha = index < MAX_NUM_ITEMS_IN_PREVIEW ? 0.5f : 0f;
float finalScale = scale * scaleRelativeToDragLayer;
dragLayer.animateView(animateView, from, to, finalAlpha,
@@ -391,7 +382,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
mBadgeInfo = badgeInfo;
}
public PreviewLayoutRule getLayoutRule() {
public ClippedFolderIconLayoutRule getLayoutRule() {
return mPreviewLayoutRule;
}
@@ -420,7 +411,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
private float getLocalCenterForIndex(int index, int curNumItems, int[] center) {
mTmpParams = mPreviewItemManager.computePreviewItemDrawingParams(
Math.min(mPreviewLayoutRule.maxNumItems(), index), curNumItems, mTmpParams);
Math.min(MAX_NUM_ITEMS_IN_PREVIEW, index), curNumItems, mTmpParams);
mTmpParams.transX += mBackground.basePreviewOffsetX;
mTmpParams.transY += mBackground.basePreviewOffsetY;
@@ -474,19 +465,17 @@ public class FolderIcon extends FrameLayout implements FolderListener {
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
} else {
saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
if (mPreviewLayoutRule.clipToBackground()) {
canvas.clipPath(mBackground.getClipPath(), Region.Op.INTERSECT);
}
canvas.clipPath(mBackground.getClipPath(), Region.Op.INTERSECT);
}
mPreviewItemManager.draw(canvas);
if (mPreviewLayoutRule.clipToBackground() && canvas.isHardwareAccelerated()) {
if (canvas.isHardwareAccelerated()) {
mBackground.clipCanvasHardware(canvas);
}
canvas.restoreToCount(saveCount);
if (mPreviewLayoutRule.clipToBackground() && !mBackground.drawingDelegated()) {
if (!mBackground.drawingDelegated()) {
mBackground.drawBackgroundStroke(canvas);
}
@@ -542,7 +531,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
itemsToDisplay.add(itemsOnPage.get(rank));
}
if (itemsToDisplay.size() == FolderIcon.NUM_ITEMS_IN_PREVIEW) {
if (itemsToDisplay.size() == MAX_NUM_ITEMS_IN_PREVIEW) {
break;
}
}
@@ -631,30 +620,6 @@ public class FolderIcon extends FrameLayout implements FolderListener {
mInfo.removeListener(mFolder);
}
public void shrinkAndFadeIn(boolean animate) {
// We remove and re-draw the FolderIcon in-case it has changed
final PreviewImageView previewImage = PreviewImageView.get(getContext());
previewImage.removeFromParent();
copyToPreview(previewImage);
clearLeaveBehindIfExists();
ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(previewImage, 1, 1, 1);
oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
oa.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// Remove the ImageView copy of the FolderIcon and make the original visible.
previewImage.removeFromParent();
setVisibility(View.VISIBLE);
}
});
oa.start();
if (!animate) {
oa.end();
}
}
public void clearLeaveBehindIfExists() {
((CellLayout.LayoutParams) getLayoutParams()).canReorder = true;
if (mInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
@@ -673,48 +638,7 @@ public class FolderIcon extends FrameLayout implements FolderListener {
}
}
public void growAndFadeOut() {
drawLeaveBehindIfExists();
// Push an ImageView copy of the FolderIcon into the DragLayer and hide the original
PreviewImageView previewImage = PreviewImageView.get(getContext());
copyToPreview(previewImage);
setVisibility(View.INVISIBLE);
ObjectAnimator oa = LauncherAnimUtils.ofViewAlphaAndScale(previewImage, 0, 1.5f, 1.5f);
oa.setDuration(getResources().getInteger(R.integer.config_folderExpandDuration));
oa.start();
}
/**
* This method draws the FolderIcon to an ImageView and then adds and positions that ImageView
* in the DragLayer in the exact absolute location of the original FolderIcon.
*/
private void copyToPreview(PreviewImageView previewImageView) {
previewImageView.copy(this);
if (mFolder != null) {
previewImageView.setPivotX(mFolder.getPivotXForIconAnimation());
previewImageView.setPivotY(mFolder.getPivotYForIconAnimation());
mFolder.bringToFront();
}
}
public void onFolderClose(int currentPage) {
mPreviewItemManager.onFolderClose(currentPage);
}
interface PreviewLayoutRule {
PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
PreviewItemDrawingParams params);
void init(int availableSpace, float intrinsicIconSize, boolean rtl);
float scaleForItem(int index, int totalNumItems);
float getIconSize();
int maxNumItems();
boolean clipToBackground();
boolean hasEnterExitIndices();
int getExitIndex();
int getEnterIndex();
}
}

View File

@@ -18,7 +18,8 @@ package com.android.launcher3.folder;
import com.android.launcher3.FolderInfo;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.config.FeatureFlags;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
/**
* Verifies whether an item in a Folder is displayed in the FolderIcon preview.
@@ -45,9 +46,7 @@ public class FolderIconPreviewVerifier {
mMaxGridCountY, mMaxItemsPerPage, mGridSize);
mGridCountX = mGridSize[0];
mDisplayingUpperLeftQuadrant = FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION
&& !FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON
&& numItemsInFolder > FolderIcon.NUM_ITEMS_IN_PREVIEW;
mDisplayingUpperLeftQuadrant = numItemsInFolder > MAX_NUM_ITEMS_IN_PREVIEW;
}
/**
@@ -70,6 +69,6 @@ public class FolderIconPreviewVerifier {
int row = rank / mGridCountX;
return col < 2 && row < 2;
}
return rank < FolderIcon.NUM_ITEMS_IN_PREVIEW;
return rank < MAX_NUM_ITEMS_IN_PREVIEW;
}
}

View File

@@ -1,97 +0,0 @@
/*
* Copyright (C) 2016 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;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.view.View;
import android.widget.ImageView;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.launcher3.dragndrop.DragLayer;
/**
* A temporary view which displays the a bitmap (used for folder icon animation)
*/
public class PreviewImageView extends ImageView {
private final Rect mTempRect = new Rect();
private final DragLayer mParent;
private Bitmap mBitmap;
private Canvas mCanvas;
public PreviewImageView(DragLayer parent) {
super(parent.getContext());
mParent = parent;
}
public void copy(View view) {
final int width = view.getMeasuredWidth();
final int height = view.getMeasuredHeight();
if (mBitmap == null || mBitmap.getWidth() != width || mBitmap.getHeight() != height) {
mBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
DragLayer.LayoutParams lp;
if (getLayoutParams() instanceof DragLayer.LayoutParams) {
lp = (DragLayer.LayoutParams) getLayoutParams();
} else {
lp = new DragLayer.LayoutParams(width, height);
}
// The layout from which the folder is being opened may be scaled, adjust the starting
// view size by this scale factor.
float scale = mParent.getDescendantRectRelativeToSelf(view, mTempRect);
lp.customPosition = true;
lp.x = mTempRect.left;
lp.y = mTempRect.top;
lp.width = (int) (scale * width);
lp.height = (int) (scale * height);
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
view.draw(mCanvas);
setImageBitmap(mBitmap);
// Just in case this image view is still in the drag layer from a previous animation,
// we remove it and re-add it.
removeFromParent();
mParent.addView(this, lp);
}
public void removeFromParent() {
if (mParent.indexOfChild(this) != -1) {
mParent.removeView(this);
}
}
public static PreviewImageView get(Context context) {
DragLayer dragLayer = Launcher.getLauncher(context).getDragLayer();
PreviewImageView view = (PreviewImageView) dragLayer.getTag(R.id.preview_image_id);
if (view == null) {
view = new PreviewImageView(dragLayer);
dragLayer.setTag(R.id.preview_image_id, view);
}
return view;
}
}

View File

@@ -29,11 +29,13 @@ import android.widget.TextView;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.ShortcutInfo;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import java.util.ArrayList;
import java.util.List;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.ENTER_INDEX;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.EXIT_INDEX;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
import static com.android.launcher3.folder.FolderIcon.DROP_IN_ANIMATION_DURATION;
/**
@@ -202,7 +204,7 @@ public class PreviewItemManager {
params.add(new PreviewItemDrawingParams(0, 0, 0, 0));
}
int numItemsInFirstPagePreview = page == 0 ? items.size() : FolderIcon.NUM_ITEMS_IN_PREVIEW;
int numItemsInFirstPagePreview = page == 0 ? items.size() : MAX_NUM_ITEMS_IN_PREVIEW;
for (int i = 0; i < params.size(); i++) {
PreviewItemDrawingParams p = params.get(i);
p.drawable = items.get(i).getCompoundDrawables()[1];
@@ -213,7 +215,7 @@ public class PreviewItemManager {
p.drawable.setCallback(mIcon);
}
if (!animate || FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON) {
if (!animate) {
computePreviewItemDrawingParams(i, numItemsInFirstPagePreview, p);
if (mReferenceDrawable == null) {
mReferenceDrawable = p.drawable;
@@ -308,7 +310,7 @@ public class PreviewItemManager {
int prevIndex = newParams.indexOf(moveIn.get(i));
PreviewItemDrawingParams p = params.get(prevIndex);
computePreviewItemDrawingParams(prevIndex, numItems, p);
updateTransitionParam(p, moveIn.get(i), mIcon.mPreviewLayoutRule.getEnterIndex(),
updateTransitionParam(p, moveIn.get(i), ENTER_INDEX,
newParams.indexOf(moveIn.get(i)));
}
@@ -328,7 +330,7 @@ public class PreviewItemManager {
BubbleTextView item = moveOut.get(i);
int oldIndex = oldParams.indexOf(item);
PreviewItemDrawingParams p = computePreviewItemDrawingParams(oldIndex, numItems, null);
updateTransitionParam(p, item, oldIndex, mIcon.mPreviewLayoutRule.getExitIndex());
updateTransitionParam(p, item, oldIndex, EXIT_INDEX);
params.add(0, p); // We want these items first so that they are on drawn last.
}
@@ -349,7 +351,7 @@ public class PreviewItemManager {
}
FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, prevIndex,
FolderIcon.NUM_ITEMS_IN_PREVIEW, newIndex, FolderIcon.NUM_ITEMS_IN_PREVIEW,
MAX_NUM_ITEMS_IN_PREVIEW, newIndex, MAX_NUM_ITEMS_IN_PREVIEW,
DROP_IN_ANIMATION_DURATION, null);
if (p.anim != null && !p.anim.hasEqualFinalState(anim)) {
p.anim.cancel();

View File

@@ -1,115 +0,0 @@
/**
* Copyright (C) 2015 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;
public class StackFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule {
static final int MAX_NUM_ITEMS_IN_PREVIEW = 3;
// The degree to which the item in the back of the stack is scaled [0...1]
// (0 means it's not scaled at all, 1 means it's scaled to nothing)
private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f;
// The amount of vertical spread between items in the stack [0...1]
private static final float PERSPECTIVE_SHIFT_FACTOR = 0.18f;
private float mBaselineIconScale;
private int mBaselineIconSize;
private int mAvailableSpaceInPreview;
private float mMaxPerspectiveShift;
@Override
public void init(int availableSpace, float intrinsicIconSize, boolean rtl) {
mAvailableSpaceInPreview = availableSpace;
// cos(45) = 0.707 + ~= 0.1) = 0.8f
int adjustedAvailableSpace = (int) ((mAvailableSpaceInPreview / 2) * (1 + 0.8f));
int unscaledHeight = (int) (intrinsicIconSize * (1 + PERSPECTIVE_SHIFT_FACTOR));
mBaselineIconScale = (1.0f * adjustedAvailableSpace / unscaledHeight);
mBaselineIconSize = (int) (intrinsicIconSize * mBaselineIconScale);
mMaxPerspectiveShift = mBaselineIconSize * PERSPECTIVE_SHIFT_FACTOR;
}
@Override
public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
PreviewItemDrawingParams params) {
float scale = scaleForItem(index, curNumItems);
index = MAX_NUM_ITEMS_IN_PREVIEW - index - 1;
float r = (index * 1.0f) / (MAX_NUM_ITEMS_IN_PREVIEW - 1);
float offset = (1 - r) * mMaxPerspectiveShift;
float scaledSize = scale * mBaselineIconSize;
float scaleOffsetCorrection = (1 - scale) * mBaselineIconSize;
// We want to imagine our coordinates from the bottom left, growing up and to the
// right. This is natural for the x-axis, but for the y-axis, we have to invert things.
float transY = mAvailableSpaceInPreview - (offset + scaledSize + scaleOffsetCorrection);
float transX = (mAvailableSpaceInPreview - scaledSize) / 2;
float totalScale = mBaselineIconScale * scale;
final float overlayAlpha = (80 * (1 - r)) / 255f;
if (params == null) {
params = new PreviewItemDrawingParams(transX, transY, totalScale, overlayAlpha);
} else {
params.update(transX, transY, totalScale);
params.overlayAlpha = overlayAlpha;
}
return params;
}
@Override
public int maxNumItems() {
return MAX_NUM_ITEMS_IN_PREVIEW;
}
@Override
public float getIconSize() {
return mBaselineIconSize;
}
@Override
public float scaleForItem(int index, int numItems) {
// Scale is determined by the position of the icon in the preview.
index = MAX_NUM_ITEMS_IN_PREVIEW - index - 1;
float r = (index * 1.0f) / (MAX_NUM_ITEMS_IN_PREVIEW - 1);
return (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r));
}
@Override
public boolean clipToBackground() {
return false;
}
@Override
public boolean hasEnterExitIndices() {
return false;
}
@Override
public int getExitIndex() {
throw new RuntimeException("hasEnterExitIndices not supported");
}
@Override
public int getEnterIndex() {
throw new RuntimeException("hasEnterExitIndices not supported");
}
}

View File

@@ -53,7 +53,6 @@ import com.android.launcher3.compat.PackageInstallerCompat;
import com.android.launcher3.compat.UserManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.Folder;
import com.android.launcher3.folder.FolderIcon;
import com.android.launcher3.folder.FolderIconPreviewVerifier;
import com.android.launcher3.graphics.LauncherIcons;
import com.android.launcher3.logging.FileLog;
@@ -76,6 +75,8 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.CancellationException;
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
/**
* Runnable for the thread that loads the contents of the launcher:
* - workspace icons
@@ -734,7 +735,7 @@ public class LoaderTask implements Runnable {
numItemsInPreview++;
}
if (numItemsInPreview >= FolderIcon.NUM_ITEMS_IN_PREVIEW) {
if (numItemsInPreview >= MAX_NUM_ITEMS_IN_PREVIEW) {
break;
}
}