Loading src/com/android/launcher3/CellLayout.java +7 −6 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper; import com.android.launcher3.anim.PropertyListBuilder; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.PreviewBackground; import com.android.launcher3.graphics.DragPreviewProvider; import com.android.launcher3.util.CellAndSpan; import com.android.launcher3.util.GridOccupancy; Loading Loading @@ -102,8 +103,8 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { private OnTouchListener mInterceptTouchListener; private final StylusEventHelper mStylusEventHelper; private final ArrayList<FolderIcon.PreviewBackground> mFolderBackgrounds = new ArrayList<>(); final FolderIcon.PreviewBackground mFolderLeaveBehind = new FolderIcon.PreviewBackground(); private final ArrayList<PreviewBackground> mFolderBackgrounds = new ArrayList<>(); final PreviewBackground mFolderLeaveBehind = new PreviewBackground(); private float mBackgroundAlpha; Loading Loading @@ -495,7 +496,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { } for (int i = 0; i < mFolderBackgrounds.size(); i++) { FolderIcon.PreviewBackground bg = mFolderBackgrounds.get(i); PreviewBackground bg = mFolderBackgrounds.get(i); cellToPoint(bg.delegateCellX, bg.delegateCellY, mTempLocation); canvas.save(); canvas.translate(mTempLocation[0], mTempLocation[1]); Loading @@ -521,7 +522,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { super.dispatchDraw(canvas); for (int i = 0; i < mFolderBackgrounds.size(); i++) { FolderIcon.PreviewBackground bg = mFolderBackgrounds.get(i); PreviewBackground bg = mFolderBackgrounds.get(i); if (bg.isClipping) { cellToPoint(bg.delegateCellX, bg.delegateCellY, mTempLocation); canvas.save(); Loading @@ -532,10 +533,10 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { } } public void addFolderBackground(FolderIcon.PreviewBackground bg) { public void addFolderBackground(PreviewBackground bg) { mFolderBackgrounds.add(bg); } public void removeFolderBackground(FolderIcon.PreviewBackground bg) { public void removeFolderBackground(PreviewBackground bg) { mFolderBackgrounds.remove(bg); } Loading src/com/android/launcher3/Workspace.java +4 −3 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.dragndrop.SpringLoadedDragController; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.PreviewBackground; import com.android.launcher3.graphics.DragPreviewProvider; import com.android.launcher3.graphics.PreloadIconDrawable; import com.android.launcher3.popup.PopupContainerWithArrow; Loading Loading @@ -254,7 +255,7 @@ public class Workspace extends PagedView public static final int REORDER_TIMEOUT = 350; private final Alarm mFolderCreationAlarm = new Alarm(); private final Alarm mReorderAlarm = new Alarm(); private FolderIcon.PreviewBackground mFolderCreateBg; private PreviewBackground mFolderCreateBg; private FolderIcon mDragOverFolderIcon = null; private boolean mCreateUserFolderOnDrop = false; private boolean mAddToExistingFolderOnDrop = false; Loading Loading @@ -2374,7 +2375,7 @@ public class Workspace extends PagedView // In order to keep everything continuous, we hand off the currently rendered // folder background to the newly created icon. This preserves animation state. fi.setFolderBackground(mFolderCreateBg); mFolderCreateBg = new FolderIcon.PreviewBackground(); mFolderCreateBg = new PreviewBackground(); fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale, postAnimationRunnable); } else { Loading Loading @@ -3055,7 +3056,7 @@ public class Workspace extends PagedView final int cellX; final int cellY; final FolderIcon.PreviewBackground bg = new FolderIcon.PreviewBackground(); final PreviewBackground bg = new PreviewBackground(); public FolderCreationAlarmListener(CellLayout layout, int cellX, int cellY) { this.layout = layout; Loading src/com/android/launcher3/folder/FolderAnimationManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ public class FolderAnimationManager { private GradientDrawable mFolderBackground; private FolderIcon mFolderIcon; private FolderIcon.PreviewBackground mPreviewBackground; private PreviewBackground mPreviewBackground; private Context mContext; private Launcher mLauncher; Loading src/com/android/launcher3/folder/FolderIcon.java +0 −401 Original line number Diff line number Diff line Loading @@ -23,21 +23,12 @@ import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.v4.graphics.ColorUtils; import android.util.AttributeSet; import android.util.Property; import android.view.LayoutInflater; Loading @@ -57,7 +48,6 @@ import com.android.launcher3.CellLayout; import com.android.launcher3.CheckLongPressHelper; import com.android.launcher3.DeviceProfile; import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.FolderInfo; import com.android.launcher3.FolderInfo.FolderListener; import com.android.launcher3.ItemInfo; Loading @@ -76,8 +66,6 @@ import com.android.launcher3.badge.FolderBadgeInfo; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.graphics.PreloadIconDrawable; import com.android.launcher3.util.Themes; import com.android.launcher3.graphics.IconPalette; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.PendingAddShortcutInfo; Loading @@ -101,8 +89,6 @@ public class FolderIcon extends FrameLayout implements FolderListener { private CheckLongPressHelper mLongPressHelper; private StylusEventHelper mStylusEventHelper; // The number of icons to display in the private static final int CONSUMPTION_ANIMATION_DURATION = 100; private static final int DROP_IN_ANIMATION_DURATION = 400; private static final int INITIAL_ITEM_ANIMATION_DURATION = 350; private static final int FINAL_ITEM_ANIMATION_DURATION = 200; Loading Loading @@ -521,393 +507,6 @@ public class FolderIcon extends FrameLayout implements FolderListener { canvas.restore(); } /** * This object represents a FolderIcon preview background. It stores drawing / measurement * information, handles drawing, and animation (accept state <--> rest state). */ public static class PreviewBackground { private final PorterDuffXfermode mClipPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN); // Create a RadialGradient such that it draws a black circle and then extends with // transparent. To achieve this, we keep the gradient to black for the range [0, 1) and // just at the edge quickly change it to transparent. private final RadialGradient mClipShader = new RadialGradient(0, 0, 1, new int[] {Color.BLACK, Color.BLACK, Color.TRANSPARENT }, new float[] {0, 0.999f, 1}, Shader.TileMode.CLAMP); private final PorterDuffXfermode mShadowPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT); private RadialGradient mShadowShader = null; private final Matrix mShaderMatrix = new Matrix(); private final Path mPath = new Path(); private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private float mScale = 1f; private float mColorMultiplier = 1f; private int mBgColor; private float mStrokeWidth; private int mStrokeAlpha = MAX_BG_OPACITY; private int mShadowAlpha = 255; private View mInvalidateDelegate; public int previewSize; private int basePreviewOffsetX; private int basePreviewOffsetY; private CellLayout mDrawingDelegate; public int delegateCellX; public int delegateCellY; // When the PreviewBackground is drawn under an icon (for creating a folder) the border // should not occlude the icon public boolean isClipping = true; // Drawing / animation configurations private static final float ACCEPT_SCALE_FACTOR = 1.25f; private static final float ACCEPT_COLOR_MULTIPLIER = 1.5f; // Expressed on a scale from 0 to 255. private static final int BG_OPACITY = 160; private static final int MAX_BG_OPACITY = 225; private static final int SHADOW_OPACITY = 40; ValueAnimator mScaleAnimator; ObjectAnimator mStrokeAlphaAnimator; ObjectAnimator mShadowAnimator; private static final Property<PreviewBackground, Integer> STROKE_ALPHA = new Property<PreviewBackground, Integer>(Integer.class, "strokeAlpha") { @Override public Integer get(PreviewBackground previewBackground) { return previewBackground.mStrokeAlpha; } @Override public void set(PreviewBackground previewBackground, Integer alpha) { previewBackground.mStrokeAlpha = alpha; previewBackground.invalidate(); } }; private static final Property<PreviewBackground, Integer> SHADOW_ALPHA = new Property<PreviewBackground, Integer>(Integer.class, "shadowAlpha") { @Override public Integer get(PreviewBackground previewBackground) { return previewBackground.mShadowAlpha; } @Override public void set(PreviewBackground previewBackground, Integer alpha) { previewBackground.mShadowAlpha = alpha; previewBackground.invalidate(); } }; public void setup(Launcher launcher, View invalidateDelegate, int availableSpace, int topPadding) { mInvalidateDelegate = invalidateDelegate; mBgColor = Themes.getAttrColor(launcher, android.R.attr.colorPrimary); DeviceProfile grid = launcher.getDeviceProfile(); final int previewSize = grid.folderIconSizePx; final int previewPadding = grid.folderIconPreviewPadding; this.previewSize = (previewSize - 2 * previewPadding); basePreviewOffsetX = (availableSpace - this.previewSize) / 2; basePreviewOffsetY = previewPadding + grid.folderBackgroundOffset + topPadding; // Stroke width is 1dp mStrokeWidth = launcher.getResources().getDisplayMetrics().density; float radius = getScaledRadius(); float shadowRadius = radius + mStrokeWidth; int shadowColor = Color.argb(SHADOW_OPACITY, 0, 0, 0); mShadowShader = new RadialGradient(0, 0, 1, new int[] {shadowColor, Color.TRANSPARENT}, new float[] {radius / shadowRadius, 1}, Shader.TileMode.CLAMP); invalidate(); } int getRadius() { return previewSize / 2; } int getScaledRadius() { return (int) (mScale * getRadius()); } int getOffsetX() { return basePreviewOffsetX - (getScaledRadius() - getRadius()); } int getOffsetY() { return basePreviewOffsetY - (getScaledRadius() - getRadius()); } /** * Returns the progress of the scale animation, where 0 means the scale is at 1f * and 1 means the scale is at ACCEPT_SCALE_FACTOR. */ float getScaleProgress() { return (mScale - 1f) / (ACCEPT_SCALE_FACTOR - 1f); } void invalidate() { if (mInvalidateDelegate != null) { mInvalidateDelegate.invalidate(); } if (mDrawingDelegate != null) { mDrawingDelegate.invalidate(); } } void setInvalidateDelegate(View invalidateDelegate) { mInvalidateDelegate = invalidateDelegate; invalidate(); } public void drawBackground(Canvas canvas) { mPaint.setStyle(Paint.Style.FILL); int alpha = (int) Math.min(MAX_BG_OPACITY, BG_OPACITY * mColorMultiplier); mPaint.setColor(ColorUtils.setAlphaComponent(mBgColor, alpha)); drawCircle(canvas, 0 /* deltaRadius */); // Draw shadow. if (mShadowShader == null) { return; } float radius = getScaledRadius(); float shadowRadius = radius + mStrokeWidth; mPaint.setColor(Color.BLACK); int offsetX = getOffsetX(); int offsetY = getOffsetY(); final int saveCount; if (canvas.isHardwareAccelerated()) { saveCount = canvas.saveLayer(offsetX - mStrokeWidth, offsetY, offsetX + radius + shadowRadius, offsetY + shadowRadius + shadowRadius, null, Canvas.CLIP_TO_LAYER_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); } else { saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG); clipCanvasSoftware(canvas, Region.Op.DIFFERENCE); } mShaderMatrix.setScale(shadowRadius, shadowRadius); mShaderMatrix.postTranslate(radius + offsetX, shadowRadius + offsetY); mShadowShader.setLocalMatrix(mShaderMatrix); mPaint.setAlpha(mShadowAlpha); mPaint.setShader(mShadowShader); canvas.drawPaint(mPaint); mPaint.setAlpha(255); mPaint.setShader(null); if (canvas.isHardwareAccelerated()) { mPaint.setXfermode(mShadowPorterDuffXfermode); canvas.drawCircle(radius + offsetX, radius + offsetY, radius, mPaint); mPaint.setXfermode(null); } canvas.restoreToCount(saveCount); } public void fadeInBackgroundShadow() { if (mShadowAnimator != null) { mShadowAnimator.cancel(); } mShadowAnimator = ObjectAnimator .ofInt(this, SHADOW_ALPHA, 0, 255) .setDuration(100); mShadowAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mShadowAnimator = null; } }); mShadowAnimator.start(); } public void animateBackgroundStroke() { if (mStrokeAlphaAnimator != null) { mStrokeAlphaAnimator.cancel(); } mStrokeAlphaAnimator = ObjectAnimator .ofInt(this, STROKE_ALPHA, MAX_BG_OPACITY / 2, MAX_BG_OPACITY) .setDuration(100); mStrokeAlphaAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mStrokeAlphaAnimator = null; } }); mStrokeAlphaAnimator.start(); } public void drawBackgroundStroke(Canvas canvas) { mPaint.setColor(ColorUtils.setAlphaComponent(mBgColor, mStrokeAlpha)); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(mStrokeWidth); drawCircle(canvas, 1 /* deltaRadius */); } public void drawLeaveBehind(Canvas canvas) { float originalScale = mScale; mScale = 0.5f; mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(Color.argb(160, 245, 245, 245)); drawCircle(canvas, 0 /* deltaRadius */); mScale = originalScale; } private void drawCircle(Canvas canvas,float deltaRadius) { float radius = getScaledRadius(); canvas.drawCircle(radius + getOffsetX(), radius + getOffsetY(), radius - deltaRadius, mPaint); } // It is the callers responsibility to save and restore the canvas layers. private void clipCanvasSoftware(Canvas canvas, Region.Op op) { mPath.reset(); float r = getScaledRadius(); mPath.addCircle(r + getOffsetX(), r + getOffsetY(), r, Path.Direction.CW); canvas.clipPath(mPath, op); } // It is the callers responsibility to save and restore the canvas layers. private void clipCanvasHardware(Canvas canvas) { mPaint.setColor(Color.BLACK); mPaint.setXfermode(mClipPorterDuffXfermode); float radius = getScaledRadius(); mShaderMatrix.setScale(radius, radius); mShaderMatrix.postTranslate(radius + getOffsetX(), radius + getOffsetY()); mClipShader.setLocalMatrix(mShaderMatrix); mPaint.setShader(mClipShader); canvas.drawPaint(mPaint); mPaint.setXfermode(null); mPaint.setShader(null); } private void delegateDrawing(CellLayout delegate, int cellX, int cellY) { if (mDrawingDelegate != delegate) { delegate.addFolderBackground(this); } mDrawingDelegate = delegate; delegateCellX = cellX; delegateCellY = cellY; invalidate(); } private void clearDrawingDelegate() { if (mDrawingDelegate != null) { mDrawingDelegate.removeFolderBackground(this); } mDrawingDelegate = null; invalidate(); } private boolean drawingDelegated() { return mDrawingDelegate != null; } private void animateScale(float finalScale, float finalMultiplier, final Runnable onStart, final Runnable onEnd) { final float scale0 = mScale; final float scale1 = finalScale; final float bgMultiplier0 = mColorMultiplier; final float bgMultiplier1 = finalMultiplier; if (mScaleAnimator != null) { mScaleAnimator.cancel(); } mScaleAnimator = LauncherAnimUtils.ofFloat(0f, 1.0f); mScaleAnimator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float prog = animation.getAnimatedFraction(); mScale = prog * scale1 + (1 - prog) * scale0; mColorMultiplier = prog * bgMultiplier1 + (1 - prog) * bgMultiplier0; invalidate(); } }); mScaleAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { if (onStart != null) { onStart.run(); } } @Override public void onAnimationEnd(Animator animation) { if (onEnd != null) { onEnd.run(); } mScaleAnimator = null; } }); mScaleAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION); mScaleAnimator.start(); } public void animateToAccept(final CellLayout cl, final int cellX, final int cellY) { Runnable onStart = new Runnable() { @Override public void run() { delegateDrawing(cl, cellX, cellY); } }; animateScale(ACCEPT_SCALE_FACTOR, ACCEPT_COLOR_MULTIPLIER, onStart, null); } public void animateToRest() { // This can be called multiple times -- we need to make sure the drawing delegate // is saved and restored at the beginning of the animation, since cancelling the // existing animation can clear the delgate. final CellLayout cl = mDrawingDelegate; final int cellX = delegateCellX; final int cellY = delegateCellY; Runnable onStart = new Runnable() { @Override public void run() { delegateDrawing(cl, cellX, cellY); } }; Runnable onEnd = new Runnable() { @Override public void run() { clearDrawingDelegate(); } }; animateScale(1f, 1f, onStart, onEnd); } public int getBackgroundAlpha() { return (int) Math.min(MAX_BG_OPACITY, BG_OPACITY * mColorMultiplier); } public float getStrokeWidth() { return mStrokeWidth; } } public void setFolderBackground(PreviewBackground bg) { mBackground = bg; mBackground.setInvalidateDelegate(this); Loading src/com/android/launcher3/folder/PreviewBackground.java 0 → 100644 +430 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
src/com/android/launcher3/CellLayout.java +7 −6 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ import com.android.launcher3.accessibility.WorkspaceAccessibilityHelper; import com.android.launcher3.anim.PropertyListBuilder; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.PreviewBackground; import com.android.launcher3.graphics.DragPreviewProvider; import com.android.launcher3.util.CellAndSpan; import com.android.launcher3.util.GridOccupancy; Loading Loading @@ -102,8 +103,8 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { private OnTouchListener mInterceptTouchListener; private final StylusEventHelper mStylusEventHelper; private final ArrayList<FolderIcon.PreviewBackground> mFolderBackgrounds = new ArrayList<>(); final FolderIcon.PreviewBackground mFolderLeaveBehind = new FolderIcon.PreviewBackground(); private final ArrayList<PreviewBackground> mFolderBackgrounds = new ArrayList<>(); final PreviewBackground mFolderLeaveBehind = new PreviewBackground(); private float mBackgroundAlpha; Loading Loading @@ -495,7 +496,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { } for (int i = 0; i < mFolderBackgrounds.size(); i++) { FolderIcon.PreviewBackground bg = mFolderBackgrounds.get(i); PreviewBackground bg = mFolderBackgrounds.get(i); cellToPoint(bg.delegateCellX, bg.delegateCellY, mTempLocation); canvas.save(); canvas.translate(mTempLocation[0], mTempLocation[1]); Loading @@ -521,7 +522,7 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { super.dispatchDraw(canvas); for (int i = 0; i < mFolderBackgrounds.size(); i++) { FolderIcon.PreviewBackground bg = mFolderBackgrounds.get(i); PreviewBackground bg = mFolderBackgrounds.get(i); if (bg.isClipping) { cellToPoint(bg.delegateCellX, bg.delegateCellY, mTempLocation); canvas.save(); Loading @@ -532,10 +533,10 @@ public class CellLayout extends ViewGroup implements BubbleTextShadowHandler { } } public void addFolderBackground(FolderIcon.PreviewBackground bg) { public void addFolderBackground(PreviewBackground bg) { mFolderBackgrounds.add(bg); } public void removeFolderBackground(FolderIcon.PreviewBackground bg) { public void removeFolderBackground(PreviewBackground bg) { mFolderBackgrounds.remove(bg); } Loading
src/com/android/launcher3/Workspace.java +4 −3 Original line number Diff line number Diff line Loading @@ -71,6 +71,7 @@ import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.dragndrop.SpringLoadedDragController; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.folder.PreviewBackground; import com.android.launcher3.graphics.DragPreviewProvider; import com.android.launcher3.graphics.PreloadIconDrawable; import com.android.launcher3.popup.PopupContainerWithArrow; Loading Loading @@ -254,7 +255,7 @@ public class Workspace extends PagedView public static final int REORDER_TIMEOUT = 350; private final Alarm mFolderCreationAlarm = new Alarm(); private final Alarm mReorderAlarm = new Alarm(); private FolderIcon.PreviewBackground mFolderCreateBg; private PreviewBackground mFolderCreateBg; private FolderIcon mDragOverFolderIcon = null; private boolean mCreateUserFolderOnDrop = false; private boolean mAddToExistingFolderOnDrop = false; Loading Loading @@ -2374,7 +2375,7 @@ public class Workspace extends PagedView // In order to keep everything continuous, we hand off the currently rendered // folder background to the newly created icon. This preserves animation state. fi.setFolderBackground(mFolderCreateBg); mFolderCreateBg = new FolderIcon.PreviewBackground(); mFolderCreateBg = new PreviewBackground(); fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale, postAnimationRunnable); } else { Loading Loading @@ -3055,7 +3056,7 @@ public class Workspace extends PagedView final int cellX; final int cellY; final FolderIcon.PreviewBackground bg = new FolderIcon.PreviewBackground(); final PreviewBackground bg = new PreviewBackground(); public FolderCreationAlarmListener(CellLayout layout, int cellX, int cellY) { this.layout = layout; Loading
src/com/android/launcher3/folder/FolderAnimationManager.java +1 −1 Original line number Diff line number Diff line Loading @@ -57,7 +57,7 @@ public class FolderAnimationManager { private GradientDrawable mFolderBackground; private FolderIcon mFolderIcon; private FolderIcon.PreviewBackground mPreviewBackground; private PreviewBackground mPreviewBackground; private Context mContext; private Launcher mLauncher; Loading
src/com/android/launcher3/folder/FolderIcon.java +0 −401 Original line number Diff line number Diff line Loading @@ -23,21 +23,12 @@ import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RadialGradient; import android.graphics.Rect; import android.graphics.Region; import android.graphics.Shader; import android.graphics.drawable.Drawable; import android.os.Parcelable; import android.support.annotation.NonNull; import android.support.v4.graphics.ColorUtils; import android.util.AttributeSet; import android.util.Property; import android.view.LayoutInflater; Loading @@ -57,7 +48,6 @@ import com.android.launcher3.CellLayout; import com.android.launcher3.CheckLongPressHelper; import com.android.launcher3.DeviceProfile; import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.FolderInfo; import com.android.launcher3.FolderInfo.FolderListener; import com.android.launcher3.ItemInfo; Loading @@ -76,8 +66,6 @@ import com.android.launcher3.badge.FolderBadgeInfo; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.graphics.PreloadIconDrawable; import com.android.launcher3.util.Themes; import com.android.launcher3.graphics.IconPalette; import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.PendingAddShortcutInfo; Loading @@ -101,8 +89,6 @@ public class FolderIcon extends FrameLayout implements FolderListener { private CheckLongPressHelper mLongPressHelper; private StylusEventHelper mStylusEventHelper; // The number of icons to display in the private static final int CONSUMPTION_ANIMATION_DURATION = 100; private static final int DROP_IN_ANIMATION_DURATION = 400; private static final int INITIAL_ITEM_ANIMATION_DURATION = 350; private static final int FINAL_ITEM_ANIMATION_DURATION = 200; Loading Loading @@ -521,393 +507,6 @@ public class FolderIcon extends FrameLayout implements FolderListener { canvas.restore(); } /** * This object represents a FolderIcon preview background. It stores drawing / measurement * information, handles drawing, and animation (accept state <--> rest state). */ public static class PreviewBackground { private final PorterDuffXfermode mClipPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN); // Create a RadialGradient such that it draws a black circle and then extends with // transparent. To achieve this, we keep the gradient to black for the range [0, 1) and // just at the edge quickly change it to transparent. private final RadialGradient mClipShader = new RadialGradient(0, 0, 1, new int[] {Color.BLACK, Color.BLACK, Color.TRANSPARENT }, new float[] {0, 0.999f, 1}, Shader.TileMode.CLAMP); private final PorterDuffXfermode mShadowPorterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT); private RadialGradient mShadowShader = null; private final Matrix mShaderMatrix = new Matrix(); private final Path mPath = new Path(); private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); private float mScale = 1f; private float mColorMultiplier = 1f; private int mBgColor; private float mStrokeWidth; private int mStrokeAlpha = MAX_BG_OPACITY; private int mShadowAlpha = 255; private View mInvalidateDelegate; public int previewSize; private int basePreviewOffsetX; private int basePreviewOffsetY; private CellLayout mDrawingDelegate; public int delegateCellX; public int delegateCellY; // When the PreviewBackground is drawn under an icon (for creating a folder) the border // should not occlude the icon public boolean isClipping = true; // Drawing / animation configurations private static final float ACCEPT_SCALE_FACTOR = 1.25f; private static final float ACCEPT_COLOR_MULTIPLIER = 1.5f; // Expressed on a scale from 0 to 255. private static final int BG_OPACITY = 160; private static final int MAX_BG_OPACITY = 225; private static final int SHADOW_OPACITY = 40; ValueAnimator mScaleAnimator; ObjectAnimator mStrokeAlphaAnimator; ObjectAnimator mShadowAnimator; private static final Property<PreviewBackground, Integer> STROKE_ALPHA = new Property<PreviewBackground, Integer>(Integer.class, "strokeAlpha") { @Override public Integer get(PreviewBackground previewBackground) { return previewBackground.mStrokeAlpha; } @Override public void set(PreviewBackground previewBackground, Integer alpha) { previewBackground.mStrokeAlpha = alpha; previewBackground.invalidate(); } }; private static final Property<PreviewBackground, Integer> SHADOW_ALPHA = new Property<PreviewBackground, Integer>(Integer.class, "shadowAlpha") { @Override public Integer get(PreviewBackground previewBackground) { return previewBackground.mShadowAlpha; } @Override public void set(PreviewBackground previewBackground, Integer alpha) { previewBackground.mShadowAlpha = alpha; previewBackground.invalidate(); } }; public void setup(Launcher launcher, View invalidateDelegate, int availableSpace, int topPadding) { mInvalidateDelegate = invalidateDelegate; mBgColor = Themes.getAttrColor(launcher, android.R.attr.colorPrimary); DeviceProfile grid = launcher.getDeviceProfile(); final int previewSize = grid.folderIconSizePx; final int previewPadding = grid.folderIconPreviewPadding; this.previewSize = (previewSize - 2 * previewPadding); basePreviewOffsetX = (availableSpace - this.previewSize) / 2; basePreviewOffsetY = previewPadding + grid.folderBackgroundOffset + topPadding; // Stroke width is 1dp mStrokeWidth = launcher.getResources().getDisplayMetrics().density; float radius = getScaledRadius(); float shadowRadius = radius + mStrokeWidth; int shadowColor = Color.argb(SHADOW_OPACITY, 0, 0, 0); mShadowShader = new RadialGradient(0, 0, 1, new int[] {shadowColor, Color.TRANSPARENT}, new float[] {radius / shadowRadius, 1}, Shader.TileMode.CLAMP); invalidate(); } int getRadius() { return previewSize / 2; } int getScaledRadius() { return (int) (mScale * getRadius()); } int getOffsetX() { return basePreviewOffsetX - (getScaledRadius() - getRadius()); } int getOffsetY() { return basePreviewOffsetY - (getScaledRadius() - getRadius()); } /** * Returns the progress of the scale animation, where 0 means the scale is at 1f * and 1 means the scale is at ACCEPT_SCALE_FACTOR. */ float getScaleProgress() { return (mScale - 1f) / (ACCEPT_SCALE_FACTOR - 1f); } void invalidate() { if (mInvalidateDelegate != null) { mInvalidateDelegate.invalidate(); } if (mDrawingDelegate != null) { mDrawingDelegate.invalidate(); } } void setInvalidateDelegate(View invalidateDelegate) { mInvalidateDelegate = invalidateDelegate; invalidate(); } public void drawBackground(Canvas canvas) { mPaint.setStyle(Paint.Style.FILL); int alpha = (int) Math.min(MAX_BG_OPACITY, BG_OPACITY * mColorMultiplier); mPaint.setColor(ColorUtils.setAlphaComponent(mBgColor, alpha)); drawCircle(canvas, 0 /* deltaRadius */); // Draw shadow. if (mShadowShader == null) { return; } float radius = getScaledRadius(); float shadowRadius = radius + mStrokeWidth; mPaint.setColor(Color.BLACK); int offsetX = getOffsetX(); int offsetY = getOffsetY(); final int saveCount; if (canvas.isHardwareAccelerated()) { saveCount = canvas.saveLayer(offsetX - mStrokeWidth, offsetY, offsetX + radius + shadowRadius, offsetY + shadowRadius + shadowRadius, null, Canvas.CLIP_TO_LAYER_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); } else { saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG); clipCanvasSoftware(canvas, Region.Op.DIFFERENCE); } mShaderMatrix.setScale(shadowRadius, shadowRadius); mShaderMatrix.postTranslate(radius + offsetX, shadowRadius + offsetY); mShadowShader.setLocalMatrix(mShaderMatrix); mPaint.setAlpha(mShadowAlpha); mPaint.setShader(mShadowShader); canvas.drawPaint(mPaint); mPaint.setAlpha(255); mPaint.setShader(null); if (canvas.isHardwareAccelerated()) { mPaint.setXfermode(mShadowPorterDuffXfermode); canvas.drawCircle(radius + offsetX, radius + offsetY, radius, mPaint); mPaint.setXfermode(null); } canvas.restoreToCount(saveCount); } public void fadeInBackgroundShadow() { if (mShadowAnimator != null) { mShadowAnimator.cancel(); } mShadowAnimator = ObjectAnimator .ofInt(this, SHADOW_ALPHA, 0, 255) .setDuration(100); mShadowAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mShadowAnimator = null; } }); mShadowAnimator.start(); } public void animateBackgroundStroke() { if (mStrokeAlphaAnimator != null) { mStrokeAlphaAnimator.cancel(); } mStrokeAlphaAnimator = ObjectAnimator .ofInt(this, STROKE_ALPHA, MAX_BG_OPACITY / 2, MAX_BG_OPACITY) .setDuration(100); mStrokeAlphaAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mStrokeAlphaAnimator = null; } }); mStrokeAlphaAnimator.start(); } public void drawBackgroundStroke(Canvas canvas) { mPaint.setColor(ColorUtils.setAlphaComponent(mBgColor, mStrokeAlpha)); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(mStrokeWidth); drawCircle(canvas, 1 /* deltaRadius */); } public void drawLeaveBehind(Canvas canvas) { float originalScale = mScale; mScale = 0.5f; mPaint.setStyle(Paint.Style.FILL); mPaint.setColor(Color.argb(160, 245, 245, 245)); drawCircle(canvas, 0 /* deltaRadius */); mScale = originalScale; } private void drawCircle(Canvas canvas,float deltaRadius) { float radius = getScaledRadius(); canvas.drawCircle(radius + getOffsetX(), radius + getOffsetY(), radius - deltaRadius, mPaint); } // It is the callers responsibility to save and restore the canvas layers. private void clipCanvasSoftware(Canvas canvas, Region.Op op) { mPath.reset(); float r = getScaledRadius(); mPath.addCircle(r + getOffsetX(), r + getOffsetY(), r, Path.Direction.CW); canvas.clipPath(mPath, op); } // It is the callers responsibility to save and restore the canvas layers. private void clipCanvasHardware(Canvas canvas) { mPaint.setColor(Color.BLACK); mPaint.setXfermode(mClipPorterDuffXfermode); float radius = getScaledRadius(); mShaderMatrix.setScale(radius, radius); mShaderMatrix.postTranslate(radius + getOffsetX(), radius + getOffsetY()); mClipShader.setLocalMatrix(mShaderMatrix); mPaint.setShader(mClipShader); canvas.drawPaint(mPaint); mPaint.setXfermode(null); mPaint.setShader(null); } private void delegateDrawing(CellLayout delegate, int cellX, int cellY) { if (mDrawingDelegate != delegate) { delegate.addFolderBackground(this); } mDrawingDelegate = delegate; delegateCellX = cellX; delegateCellY = cellY; invalidate(); } private void clearDrawingDelegate() { if (mDrawingDelegate != null) { mDrawingDelegate.removeFolderBackground(this); } mDrawingDelegate = null; invalidate(); } private boolean drawingDelegated() { return mDrawingDelegate != null; } private void animateScale(float finalScale, float finalMultiplier, final Runnable onStart, final Runnable onEnd) { final float scale0 = mScale; final float scale1 = finalScale; final float bgMultiplier0 = mColorMultiplier; final float bgMultiplier1 = finalMultiplier; if (mScaleAnimator != null) { mScaleAnimator.cancel(); } mScaleAnimator = LauncherAnimUtils.ofFloat(0f, 1.0f); mScaleAnimator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float prog = animation.getAnimatedFraction(); mScale = prog * scale1 + (1 - prog) * scale0; mColorMultiplier = prog * bgMultiplier1 + (1 - prog) * bgMultiplier0; invalidate(); } }); mScaleAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { if (onStart != null) { onStart.run(); } } @Override public void onAnimationEnd(Animator animation) { if (onEnd != null) { onEnd.run(); } mScaleAnimator = null; } }); mScaleAnimator.setDuration(CONSUMPTION_ANIMATION_DURATION); mScaleAnimator.start(); } public void animateToAccept(final CellLayout cl, final int cellX, final int cellY) { Runnable onStart = new Runnable() { @Override public void run() { delegateDrawing(cl, cellX, cellY); } }; animateScale(ACCEPT_SCALE_FACTOR, ACCEPT_COLOR_MULTIPLIER, onStart, null); } public void animateToRest() { // This can be called multiple times -- we need to make sure the drawing delegate // is saved and restored at the beginning of the animation, since cancelling the // existing animation can clear the delgate. final CellLayout cl = mDrawingDelegate; final int cellX = delegateCellX; final int cellY = delegateCellY; Runnable onStart = new Runnable() { @Override public void run() { delegateDrawing(cl, cellX, cellY); } }; Runnable onEnd = new Runnable() { @Override public void run() { clearDrawingDelegate(); } }; animateScale(1f, 1f, onStart, onEnd); } public int getBackgroundAlpha() { return (int) Math.min(MAX_BG_OPACITY, BG_OPACITY * mColorMultiplier); } public float getStrokeWidth() { return mStrokeWidth; } } public void setFolderBackground(PreviewBackground bg) { mBackground = bg; mBackground.setInvalidateDelegate(this); Loading
src/com/android/launcher3/folder/PreviewBackground.java 0 → 100644 +430 −0 File added.Preview size limit exceeded, changes collapsed. Show changes