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

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

Merge "Updating the task swipe-down UI" into ub-launcher3-edmonton

parents e8cf0ae6 7d2e4091
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.quickstep.fallback;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.support.annotation.AnyThread;
import android.util.AttributeSet;
import android.view.View;

+77 −0
Original line number Diff line number Diff line
@@ -15,15 +15,23 @@
 */
package com.android.quickstep.util;

import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
import android.graphics.Rect;
import android.graphics.RectF;

import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.systemui.shared.recents.utilities.RectFEvaluator;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.TransactionCompat;
import com.android.systemui.shared.system.WindowManagerWrapper;

/**
 * Utility class to handle window clip animation
@@ -126,4 +134,73 @@ public class ClipAnimationHelper {
            mTargetRect.offset(offsetX, offsetY);
        }
    }

    public void fromTaskThumbnailView(TaskThumbnailView ttv) {
        BaseDraggingActivity activity = BaseDraggingActivity.fromContext(ttv.getContext());
        BaseDragLayer dl = activity.getDragLayer();

        int[] pos = new int[2];
        dl.getLocationOnScreen(pos);
        mHomeStackBounds.set(0, 0, dl.getWidth(), dl.getHeight());
        mHomeStackBounds.offset(pos[0], pos[1]);

        if (activity.isInMultiWindowModeCompat()) {
            // TODO: Fetch multi-window target bounds from system-ui
            DeviceProfile fullDp = activity.getDeviceProfile().getFullScreenProfile();
            // Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
            // account for system insets
            int taskWidth = fullDp.availableWidthPx;
            int taskHeight = fullDp.availableHeightPx;
            int halfDividerSize = activity.getResources()
                    .getDimensionPixelSize(R.dimen.multi_window_task_divider_size) / 2;

            Rect insets = new Rect();
            WindowManagerWrapper.getInstance().getStableInsets(insets);
            if (fullDp.isLandscape) {
                taskWidth = taskWidth / 2 - halfDividerSize;
            } else {
                taskHeight = taskHeight / 2 - halfDividerSize;
            }

            mSourceStackBounds.set(0, 0, taskWidth, taskHeight);
            // Align the task to bottom right (probably not true for seascape).
            mSourceStackBounds.offset(insets.left + fullDp.availableWidthPx - taskWidth,
                    insets.top + fullDp.availableHeightPx - taskHeight);
        } else {
            mSourceStackBounds.set(mHomeStackBounds);
            mSourceInsets.set(activity.getDeviceProfile().getInsets());
        }

        Rect targetRect = new Rect();
        dl.getDescendantRectRelativeToSelf(ttv, targetRect);
        updateTargetRect(targetRect);

        // Transform the clip relative to the target rect.
        float scale = mTargetRect.width() / mSourceRect.width();
        mSourceWindowClipInsets.left = mSourceWindowClipInsets.left * scale;
        mSourceWindowClipInsets.top = mSourceWindowClipInsets.top * scale;
        mSourceWindowClipInsets.right = mSourceWindowClipInsets.right * scale;
        mSourceWindowClipInsets.bottom = mSourceWindowClipInsets.bottom * scale;
    }

    public void drawForProgress(TaskThumbnailView ttv, Canvas canvas, float progress) {
        RectF currentRect;
        synchronized (mTargetRect) {
            currentRect =  mRectFEvaluator.evaluate(progress, mSourceRect, mTargetRect);
        }

        canvas.translate(mSourceStackBounds.left - mHomeStackBounds.left,
                mSourceStackBounds.top - mHomeStackBounds.top);
        mTmpMatrix.setRectToRect(mTargetRect, currentRect, ScaleToFit.FILL);
        canvas.concat(mTmpMatrix);
        canvas.translate(mTargetRect.left, mTargetRect.top);

        float insetProgress = (1 - progress);
        ttv.drawOnCanvas(canvas,
                -mSourceWindowClipInsets.left * insetProgress,
                -mSourceWindowClipInsets.top * insetProgress,
                ttv.getMeasuredWidth() + mSourceWindowClipInsets.right * insetProgress,
                ttv.getMeasuredHeight() + mSourceWindowClipInsets.bottom * insetProgress,
                ttv.getCornerRadius() * progress);
    }
}
+100 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2018 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.quickstep.util;

import android.animation.TimeInterpolator;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.util.FloatProperty;
import android.widget.ImageView;

import com.android.launcher3.Utilities;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskThumbnailView;
import com.android.quickstep.views.TaskView;

public class TaskViewDrawable extends Drawable {

    public static FloatProperty<TaskViewDrawable> PROGRESS =
            new FloatProperty<TaskViewDrawable>("progress") {
                @Override
                public void setValue(TaskViewDrawable taskViewDrawable, float v) {
                    taskViewDrawable.setProgress(v);
                }

                @Override
                public Float get(TaskViewDrawable taskViewDrawable) {
                    return taskViewDrawable.mProgress;
                }
            };

    private static final TimeInterpolator ICON_SIZE_INTERPOLATOR =
            (t) -> (Math.max(t, 0.3f) - 0.3f) / 0.7f;

    private final RecentsView mParent;
    private final ImageView mIconView;
    private final int[] mIconPos;

    private final TaskThumbnailView mThumbnailView;

    private final ClipAnimationHelper mClipAnimationHelper;

    private float mProgress = 1;

    public TaskViewDrawable(TaskView tv, RecentsView parent) {
        mParent = parent;
        mIconView = tv.getIconView();
        mIconPos = new int[2];
        Utilities.getDescendantCoordRelativeToAncestor(mIconView, parent, mIconPos, true);

        mThumbnailView = tv.getThumbnail();
        mClipAnimationHelper = new ClipAnimationHelper();
        mClipAnimationHelper.fromTaskThumbnailView(mThumbnailView);
    }

    public void setProgress(float progress) {
        mProgress = progress;
        mParent.invalidate();
    }

    @Override
    public void draw(Canvas canvas) {
        canvas.save();
        canvas.translate(mParent.getScrollX(), mParent.getScrollY());
        mClipAnimationHelper.drawForProgress(mThumbnailView, canvas, mProgress);
        canvas.restore();

        canvas.save();
        canvas.translate(mIconPos[0], mIconPos[1]);
        float scale = ICON_SIZE_INTERPOLATOR.getInterpolation(mProgress);
        canvas.scale(scale, scale, mIconView.getWidth() / 2, mIconView.getHeight() / 2);
        mIconView.draw(canvas);
        canvas.restore();
    }

    @Override
    public void setAlpha(int i) { }

    @Override
    public void setColorFilter(ColorFilter colorFilter) { }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -130,4 +130,12 @@ public class LauncherRecentsView extends RecentsView<Launcher> {
    protected void getTaskSize(DeviceProfile dp, Rect outRect) {
        LayoutUtils.calculateLauncherTaskSize(getContext(), dp, outRect);
    }

    @Override
    protected void onTaskLaunched(boolean success) {
        if (success) {
            mActivity.getStateManager().goToState(NORMAL, false /* animate */);
        }
        super.onTaskLaunched(success);
    }
}
+23 −15
Original line number Diff line number Diff line
@@ -66,10 +66,10 @@ import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.Themes;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.QuickScrubController;
import com.android.quickstep.RecentsAnimationInterpolator;
import com.android.quickstep.RecentsAnimationInterpolator.TaskWindowBounds;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.TaskViewDrawable;
import com.android.systemui.shared.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.shared.recents.model.RecentsTaskLoader;
import com.android.systemui.shared.recents.model.Task;
@@ -79,6 +79,7 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.TaskStackChangeListener;

import java.util.ArrayList;
import java.util.function.Consumer;

/**
 * A list of recent tasks.
@@ -522,7 +523,6 @@ public abstract class RecentsView<T extends BaseActivity>
        mHasVisibleTaskData.clear();
    }


    protected abstract void onAllTasksRemoved();

    public void reset() {
@@ -1060,23 +1060,27 @@ public abstract class RecentsView<T extends BaseActivity>
            return new PendingAnimation(anim);
        }

        final RecentsAnimationInterpolator recentsInterpolator = tv.getRecentsInterpolator();
        ValueAnimator targetViewAnim = ValueAnimator.ofFloat(0, 1);
        targetViewAnim.addUpdateListener((animation) -> {
            float percent = animation.getAnimatedFraction();
            TaskWindowBounds tw = recentsInterpolator.interpolate(percent);
            tv.setScaleX(tw.taskScale);
            tv.setScaleY(tw.taskScale);
            tv.setTranslationX(tw.taskX);
            tv.setTranslationY(tw.taskY);
        });
        anim.play(targetViewAnim);
        tv.setVisibility(INVISIBLE);
        TaskViewDrawable drawable = new TaskViewDrawable(tv, this);
        getOverlay().add(drawable);

        ObjectAnimator drawableAnim =
                ObjectAnimator.ofFloat(drawable, TaskViewDrawable.PROGRESS, 1, 0);
        drawableAnim.setInterpolator(LINEAR);

        anim.play(drawableAnim);
        anim.setDuration(duration);

        Consumer<Boolean> onTaskLaunchFinish = (r) -> {
            onTaskLaunched(r);
            tv.setVisibility(VISIBLE);
            getOverlay().remove(drawable);
        };

        mPendingAnimation = new PendingAnimation(anim);
        mPendingAnimation.addEndListener((onEndListener) -> {
            if (onEndListener.isSuccess) {
                tv.launchTask(false);
                tv.launchTask(false, onTaskLaunchFinish, getHandler());
                Task task = tv.getTask();
                if (task != null) {
                    mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(
@@ -1084,13 +1088,17 @@ public abstract class RecentsView<T extends BaseActivity>
                            TaskUtils.getComponentKeyForTask(task.key));
                }
            } else {
                resetTaskVisuals();
                onTaskLaunchFinish.accept(false);
            }
            mPendingAnimation = null;
        });
        return mPendingAnimation;
    }

    protected void onTaskLaunched(boolean success) {
        resetTaskVisuals();
    }

    @Override
    protected void notifyPageSwitchListener(int prevPage) {
        super.notifyPageSwitchListener(prevPage);
Loading