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

Commit e941bc7f authored by Steven Ng's avatar Steven Ng Committed by Android (Google) Code Review
Browse files

Merge "Inflate LauncherAppWidgetHostView directly in DragView" into sc-dev

parents f1f7b9ae 3242720c
Loading
Loading
Loading
Loading
+4 −5
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ import com.android.launcher3.LauncherSettings.Favorites;
import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
import com.android.launcher3.folder.PreviewBackground;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.util.CellAndSpan;
@@ -70,6 +69,7 @@ import com.android.launcher3.util.ParcelableSparseArray;
import com.android.launcher3.util.Themes;
import com.android.launcher3.util.Thunk;
import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.widget.LauncherAppWidgetHostView;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -1065,15 +1065,14 @@ public class CellLayout extends ViewGroup {
    private void applyColorExtractionOnWidget(DropTarget.DragObject dragObject, int[] targetCell,
            int spanX, int spanY) {
        // Apply local extracted color if the DragView is an AppWidgetHostViewDrawable.
        Drawable drawable = dragObject.dragView.getDrawable();
        if (drawable instanceof AppWidgetHostViewDrawable) {
        View view = dragObject.dragView.getContentView();
        if (view instanceof LauncherAppWidgetHostView) {
            Workspace workspace =
                    Launcher.getLauncher(dragObject.dragView.getContext()).getWorkspace();
            int screenId = workspace.getIdForScreen(this);
            int pageId = workspace.getPageIndexForScreenId(screenId);
            AppWidgetHostViewDrawable hostViewDrawable = ((AppWidgetHostViewDrawable) drawable);
            cellToRect(targetCell[0], targetCell[1], spanX, spanY, mTempRect);
            hostViewDrawable.getAppWidgetHostView().handleDrag(mTempRect, pageId);
            ((LauncherAppWidgetHostView) view).handleDrag(mTempRect, pageId);
        }
    }

+52 −23
Original line number Diff line number Diff line
@@ -69,7 +69,6 @@ import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dot.FolderDotInfo;
import com.android.launcher3.dragndrop.AppWidgetHostViewDrawable;
import com.android.launcher3.dragndrop.DragController;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.dragndrop.DragOptions;
@@ -414,7 +413,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
        }

        if (mDragInfo != null && mDragInfo.cell != null) {
            CellLayout layout = (CellLayout) mDragInfo.cell.getParent().getParent();
            CellLayout layout = (CellLayout) (mDragInfo.cell instanceof LauncherAppWidgetHostView
                    ? dragObject.dragView.getContentViewParent().getParent()
                    : mDragInfo.cell.getParent().getParent());
            layout.markCellsAsUnoccupiedForView(mDragInfo.cell);
        }

@@ -1527,10 +1528,19 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
            draggableView = (DraggableView) child;
        }

        final View contentView = previewProvider.getContentView();
        final float scale;
        // The draggable drawable follows the touch point around on the screen
        final Drawable drawable = previewProvider.createDrawable();
        final Drawable drawable;
        if (contentView == null) {
            drawable = previewProvider.createDrawable();
            scale = previewProvider.getScaleAndPosition(drawable, mTempXY);
        } else {
            drawable = null;
            scale = previewProvider.getScaleAndPosition(contentView, mTempXY);
        }

        int halfPadding = previewProvider.previewPadding / 2;
        float scale = previewProvider.getScaleAndPosition(drawable, mTempXY);
        int dragLayerX = mTempXY[0];
        int dragLayerY = mTempXY[1];

@@ -1556,10 +1566,25 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
            }
        }

        if (drawable instanceof AppWidgetHostViewDrawable) {
        final DragView dv;
        if (contentView instanceof View) {
            if (contentView instanceof LauncherAppWidgetHostView) {
                mDragController.addDragListener(new AppWidgetHostViewDragListener(mLauncher));
            }
        DragView dv = mDragController.startDrag(
            dv = mDragController.startDrag(
                    contentView,
                    draggableView,
                    dragLayerX,
                    dragLayerY,
                    source,
                    dragObject,
                    dragVisualizeOffset,
                    dragRect,
                    scale * iconScale,
                    scale,
                    dragOptions);
        } else {
            dv = mDragController.startDrag(
                    drawable,
                    draggableView,
                    dragLayerX,
@@ -1571,6 +1596,7 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
                    scale * iconScale,
                    scale,
                    dragOptions);
        }
        return dv;
    }

@@ -1900,6 +1926,8 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
                        CellLayout parentCell = getParentCellLayoutForView(cell);
                        if (parentCell != null) {
                            parentCell.removeView(cell);
                        } else if (mDragInfo.cell instanceof LauncherAppWidgetHostView) {
                            d.dragView.detachContentView(/* reattachToPreviousParent= */ false);
                        } else if (FeatureFlags.IS_STUDIO_BUILD) {
                            throw new NullPointerException("mDragInfo.cell has null parent");
                        }
@@ -1938,6 +1966,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
                    if (!returnToOriginalCellToPreventShuffling) {
                        onNoCellFound(dropTargetLayout);
                    }
                    if (mDragInfo.cell instanceof LauncherAppWidgetHostView) {
                        d.dragView.detachContentView(/* reattachToPreviousParent= */ true);
                    }

                    // If we can't find a drop location, we return the item to its original position
                    CellLayout.LayoutParams lp = (CellLayout.LayoutParams) cell.getLayoutParams();
@@ -2636,10 +2667,6 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
    }

    private Drawable createWidgetDrawable(ItemInfo widgetInfo, View layout) {
        if (layout instanceof LauncherAppWidgetHostView) {
            return new AppWidgetHostViewDrawable((LauncherAppWidgetHostView) layout);
        }

        int[] unScaledSize = estimateItemSize(widgetInfo);
        int visibility = layout.getVisibility();
        layout.setVisibility(VISIBLE);
@@ -2720,7 +2747,9 @@ public class Workspace extends PagedView<WorkspacePageIndicator>

        boolean isWidget = info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET ||
                info.itemType == LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET;
        if ((animationType == ANIMATE_INTO_POSITION_AND_RESIZE || external) && finalView != null) {
        if ((animationType == ANIMATE_INTO_POSITION_AND_RESIZE || external)
                && finalView != null
                && dragView.getContentView() != finalView) {
            Drawable crossFadeDrawable = createWidgetDrawable(info, finalView);
            dragView.crossFadeContent(crossFadeDrawable, (int) (duration * 0.8f));
        } else if (isWidget && external) {
+0 −88
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.dragndrop;

import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;

import com.android.launcher3.widget.LauncherAppWidgetHostView;

/**
 * A drawable which renders {@link LauncherAppWidgetHostView} to a canvas.
 *
 * TODO(b/183609936) Stop using that class and remove it.
 */
public final class AppWidgetHostViewDrawable extends Drawable {

    private final LauncherAppWidgetHostView mAppWidgetHostView;
    private Paint mPaint = new Paint();

    public AppWidgetHostViewDrawable(LauncherAppWidgetHostView appWidgetHostView) {
        mAppWidgetHostView = appWidgetHostView;
    }

    @Override
    public void draw(Canvas canvas) {
        int saveCount = canvas.saveLayer(0, 0, getIntrinsicWidth(), getIntrinsicHeight(), mPaint);
        mAppWidgetHostView.draw(canvas);
        canvas.restoreToCount(saveCount);
    }

    @Override
    public int getIntrinsicWidth() {
        return mAppWidgetHostView.getMeasuredWidth();
    }

    @Override
    public int getIntrinsicHeight() {
        return mAppWidgetHostView.getMeasuredHeight();
    }

    @Override
    public int getOpacity() {
        // This is up to app widget provider. We don't know if the host view will cover anything
        // behind the drawable.
        return PixelFormat.UNKNOWN;
    }

    @Override
    public void setAlpha(int alpha) {
        mPaint.setAlpha(alpha);
    }

    @Override
    public int getAlpha() {
        return mPaint.getAlpha();
    }

    @Override
    public void setColorFilter(ColorFilter colorFilter) {
        mPaint.setColorFilter(colorFilter);
    }

    @Override
    public ColorFilter getColorFilter() {
        return mPaint.getColorFilter();
    }

    /** Returns the {@link LauncherAppWidgetHostView}. */
    public LauncherAppWidgetHostView getAppWidgetHostView() {
        return mAppWidgetHostView;
    }
}
+86 −15
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@ import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

import androidx.annotation.Nullable;

import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget;
@@ -125,20 +127,23 @@ public class DragController implements DragDriver.EventListener, TouchController

    /**
     * Starts a drag.
     * When the drag is started, the UI automatically goes into spring loaded mode. On a successful
     * drop, it is the responsibility of the {@link DropTarget} to exit out of the spring loaded
     * mode. If the drop was cancelled for some reason, the UI will automatically exit out of this mode.
     *
     * <p>When the drag is started, the UI automatically goes into spring loaded mode. On a
     * successful drop, it is the responsibility of the {@link DropTarget} to exit out of the spring
     * loaded mode. If the drop was cancelled for some reason, the UI will automatically exit out of
     * this mode.
     *
     * @param drawable The drawable to be displayed in the drag view.  It will be re-scaled to the
     *                 enlarged size.
     * @param originalView The source view (ie. icon, widget etc.) that is being dragged
     *          and which the DragView represents
     * @param originalView The source view (ie. icon, widget etc.) that is being dragged and which
     *                     the DragView represents
     * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
     * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
     * @param source An object representing where the drag originated
     * @param dragInfo The data associated with the object that is being dragged
     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
     *          Makes dragging feel more precise, e.g. you can clip out a transparent border
     *                   Makes dragging feel more precise, e.g. you can clip out a transparent
     *                   border
     */
    public DragView startDrag(
            Drawable drawable,
@@ -152,6 +157,61 @@ public class DragController implements DragDriver.EventListener, TouchController
            float initialDragViewScale,
            float dragViewScaleOnDrop,
            DragOptions options) {
        return startDrag(drawable, /* view= */ null, originalView, dragLayerX, dragLayerY,
                source, dragInfo, dragOffset, dragRegion, initialDragViewScale, dragViewScaleOnDrop,
                options);
    }

    /**
     * Starts a drag.
     *
     * <p>When the drag is started, the UI automatically goes into spring loaded mode. On a
     * successful drop, it is the responsibility of the {@link DropTarget} to exit out of the spring
     * loaded mode. If the drop was cancelled for some reason, the UI will automatically exit out of
     * this mode.
     *
     * @param view The view to be displayed in the drag view.  It will be re-scaled to the
     *             enlarged size.
     * @param originalView The source view (ie. icon, widget etc.) that is being dragged and which
     *                     the DragView represents
     * @param dragLayerX The x position in the DragLayer of the left-top of the bitmap.
     * @param dragLayerY The y position in the DragLayer of the left-top of the bitmap.
     * @param source An object representing where the drag originated
     * @param dragInfo The data associated with the object that is being dragged
     * @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
     *                   Makes dragging feel more precise, e.g. you can clip out a transparent
     *                   border
     */
    public DragView startDrag(
            View view,
            DraggableView originalView,
            int dragLayerX,
            int dragLayerY,
            DragSource source,
            ItemInfo dragInfo,
            Point dragOffset,
            Rect dragRegion,
            float initialDragViewScale,
            float dragViewScaleOnDrop,
            DragOptions options) {
        return startDrag(/* drawable= */ null, view, originalView, dragLayerX, dragLayerY,
                source, dragInfo, dragOffset, dragRegion, initialDragViewScale, dragViewScaleOnDrop,
                options);
    }

    private DragView startDrag(
            @Nullable Drawable drawable,
            @Nullable View view,
            DraggableView originalView,
            int dragLayerX,
            int dragLayerY,
            DragSource source,
            ItemInfo dragInfo,
            Point dragOffset,
            Rect dragRegion,
            float initialDragViewScale,
            float dragViewScaleOnDrop,
            DragOptions options) {
        if (PROFILE_DRAWING_DURING_DRAG) {
            android.os.Debug.startMethodTracing("Launcher");
        }
@@ -182,13 +242,24 @@ public class DragController implements DragDriver.EventListener, TouchController
        final Resources res = mLauncher.getResources();
        final float scaleDps = mIsInPreDrag
                ? res.getDimensionPixelSize(R.dimen.pre_drag_view_scale) : 0f;
        final DragView dragView = mDragObject.dragView = new DragView(
        final DragView dragView = mDragObject.dragView = drawable != null
                ? new DragView(
                    mLauncher,
                    drawable,
                    registrationX,
                    registrationY,
                    initialDragViewScale,
                    dragViewScaleOnDrop,
                    scaleDps)
                : new DragView(
                    mLauncher,
                    view,
                    view.getMeasuredWidth(),
                    view.getMeasuredHeight(),
                    registrationX,
                    registrationY,
                    initialDragViewScale,
                    dragViewScaleOnDrop,
                    scaleDps);
        dragView.setItemInfo(dragInfo);
        mDragObject.dragComplete = false;
+58 −3
Original line number Diff line number Diff line
@@ -42,9 +42,11 @@ import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.ImageView;

import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.FloatPropertyCompat;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
@@ -69,6 +71,10 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
    public static final int VIEW_ZOOM_DURATION = 150;

    private final View mContent;
    // The following are only used for rendering mContent directly during drag-n-drop.
    @Nullable private ViewGroup.LayoutParams mContentViewLayoutParams;
    @Nullable private ViewGroup mContentViewParent;
    private int mContentViewInParentViewIndex = -1;
    private final int mWidth;
    private final int mHeight;

@@ -135,6 +141,13 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
        mContent = content;
        mWidth = width;
        mHeight = height;
        mContentViewLayoutParams = mContent.getLayoutParams();
        if (mContent.getParent() instanceof ViewGroup) {
            mContentViewParent = (ViewGroup) mContent.getParent();
            mContentViewInParentViewIndex = mContentViewParent.indexOfChild(mContent);
            mContentViewParent.removeView(mContent);
        }

        addView(content, new LayoutParams(width, height));

        final float scale = (width + finalScaleDps) / width;
@@ -372,6 +385,12 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
        BaseDragLayer.LayoutParams lp = new BaseDragLayer.LayoutParams(mWidth, mHeight);
        lp.customPosition = true;
        setLayoutParams(lp);

        if (mContent != null) {
            // At the drag start, the source view visibility is set to invisible.
            mContent.setVisibility(VISIBLE);
        }

        move(touchX, touchY);
        // Post the animation to skip other expensive work happening on the first frame
        post(mAnim::start);
@@ -430,6 +449,33 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
        setTranslationY(mLastTouchY - mRegistrationY + mAnimatedShiftY);
    }


    /**
     * Detaches {@link #mContent}, if previously attached, from this view.
     *
     * <p>In the case of no change in the drop position, sets {@code reattachToPreviousParent} to
     * {@code true} to attach the {@link #mContent} back to its previous parent.
     */
    public void detachContentView(boolean reattachToPreviousParent) {
        if (mContent != null && mContentViewParent != null && mContentViewInParentViewIndex >= 0) {
            removeView(mContent);
            mContent.setLayoutParams(mContentViewLayoutParams);
            if (reattachToPreviousParent) {
                mContentViewParent.addView(mContent, mContentViewInParentViewIndex);
            }
            mContentViewParent = null;
            mContentViewInParentViewIndex = -1;
        }
    }

    /**
     * Removes this view from the {@link DragLayer}.
     *
     * <p>If the drag content is a {@link #mContent}, this call doesn't reattach the
     * {@link #mContent} back to its previous parent. To reattach to previous parent, the caller
     * should call {@link #detachContentView} with {@code reattachToPreviousParent} sets to true
     * before this call.
     */
    public void remove() {
        if (getParent() != null) {
            mDragLayer.removeView(DragView.this);
@@ -449,9 +495,18 @@ public class DragView extends FrameLayout implements StateListener<LauncherState
        return false;
    }

    /** Returns the current {@link Drawable} that is rendered in this view. */
    public Drawable getDrawable() {
        return mContent instanceof ImageView ? ((ImageView) mContent).getDrawable() : null;
    /** Returns the current content view that is rendered in the drag view. */
    public View getContentView() {
        return mContent;
    }

    /**
     * Returns the previous {@link ViewGroup} parent of the {@link #mContent} before the drag
     * content is attached to this view.
     */
    @Nullable
    public ViewGroup getContentViewParent() {
        return mContentViewParent;
    }

    private static class SpringFloatValue {
Loading