Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8a87856d authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Move PreviewBackground into its own class file." into ub-launcher3-dorval-polish

parents 9e83ba5a a0233f72
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -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;
@@ -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;

@@ -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]);
@@ -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();
@@ -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);
    }

+4 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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 {
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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;
+0 −401
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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;
@@ -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;
@@ -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);
+430 −0

File added.

Preview size limit exceeded, changes collapsed.