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

Commit eb9cc9db authored by Matthew Ng's avatar Matthew Ng
Browse files

Animate the long press icon scale for task menu to match task view

Use scale listeners to track each other's icon scale to match them.

Test: go to recents and long press icon
Fixes: 110789415
Change-Id: I9bba3130ecf1d099db9708c84e709d16f5906c36
parent 1f8cbcf1
Loading
Loading
Loading
Loading
+10 −2
Original line number Diff line number Diff line
@@ -24,11 +24,19 @@
    android:orientation="vertical"
    android:visibility="invisible">

    <com.android.quickstep.views.IconView
      android:id="@+id/task_icon"
      android:layout_width="@dimen/task_thumbnail_icon_size"
      android:layout_height="@dimen/task_thumbnail_icon_size"
      android:layout_gravity="top|center_horizontal"
      android:layout_marginBottom="@dimen/deep_shortcut_drawable_padding"
      android:focusable="false"
      android:importantForAccessibility="no" />

    <TextView
        android:id="@+id/task_icon_and_name"
        android:id="@+id/task_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawablePadding="@dimen/deep_shortcut_drawable_padding"
        android:gravity="center_horizontal"
        android:layout_marginBottom="16dp"
        android:textSize="12sp"/>
+39 −0
Original line number Diff line number Diff line
@@ -18,8 +18,11 @@ package com.android.quickstep.views;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.View;
import com.android.launcher3.FastBitmapDrawable;
import java.util.ArrayList;

/**
 * A view which draws a drawable stretched to fit its size. Unlike ImageView, it avoids relayout
@@ -27,8 +30,14 @@ import android.view.View;
 */
public class IconView extends View {

    public interface OnScaleUpdateListener {
        public void onScaleUpdate(float scale);
    }

    private Drawable mDrawable;

    private ArrayList<OnScaleUpdateListener> mScaleListeners;

    public IconView(Context context) {
        super(context);
    }
@@ -53,6 +62,10 @@ public class IconView extends View {
        invalidate();
    }

    public Drawable getDrawable() {
        return mDrawable;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
@@ -77,6 +90,16 @@ public class IconView extends View {
        }
    }

    @Override
    public void invalidateDrawable(@NonNull Drawable drawable) {
        super.invalidateDrawable(drawable);
        if (drawable instanceof FastBitmapDrawable && mScaleListeners != null) {
            for (OnScaleUpdateListener listener : mScaleListeners) {
                listener.onScaleUpdate(((FastBitmapDrawable) drawable).getScale());
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (mDrawable != null) {
@@ -88,4 +111,20 @@ public class IconView extends View {
    public boolean hasOverlappingRendering() {
        return false;
    }

    public void addUpdateScaleListener(OnScaleUpdateListener listener) {
        if (mScaleListeners == null) {
            mScaleListeners = new ArrayList<>();
        }
        mScaleListeners.add(listener);
        if (mDrawable instanceof FastBitmapDrawable) {
            listener.onScaleUpdate(((FastBitmapDrawable) mDrawable).getScale());
        }
    }

    public void removeUpdateScaleListener(OnScaleUpdateListener listener) {
        if (mScaleListeners != null) {
            mScaleListeners.remove(listener);
        }
    }
}
+52 −11
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
@@ -34,15 +33,16 @@ import android.widget.TextView;

import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.TaskSystemShortcut;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.views.IconView.OnScaleUpdateListener;

/**
 * Contains options for a recent task when long-pressing its icon.
@@ -59,14 +59,41 @@ public class TaskMenuView extends AbstractFloatingView {
            new TaskSystemShortcut.Install(),
    };

    private final OnScaleUpdateListener mTaskViewIconScaleListener = new OnScaleUpdateListener() {
        @Override
        public void onScaleUpdate(float scale) {
            final Drawable drawable = mTaskIcon.getDrawable();
            if (drawable instanceof FastBitmapDrawable) {
                if (scale != ((FastBitmapDrawable) drawable).getScale()) {
                    mMenuIconDrawable.setScale(scale);
                }
            }
        }
    };

    private final OnScaleUpdateListener mMenuIconScaleListener = new OnScaleUpdateListener() {
        @Override
        public void onScaleUpdate(float scale) {
            final Drawable taskViewDrawable = mTaskView.getIconView().getDrawable();
            if (taskViewDrawable instanceof FastBitmapDrawable) {
                final float currentScale = ((FastBitmapDrawable) taskViewDrawable).getScale();
                if (currentScale != scale) {
                    ((FastBitmapDrawable) taskViewDrawable).setScale(scale);
                }
            }
        }
    };

    private static final int REVEAL_OPEN_DURATION = 150;
    private static final int REVEAL_CLOSE_DURATION = 100;

    private BaseDraggingActivity mActivity;
    private TextView mTaskIconAndName;
    private TextView mTaskName;
    private IconView mTaskIcon;
    private AnimatorSet mOpenCloseAnimator;
    private TaskView mTaskView;
    private LinearLayout mOptionLayout;
    private FastBitmapDrawable mMenuIconDrawable;

    public TaskMenuView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
@@ -81,7 +108,8 @@ public class TaskMenuView extends AbstractFloatingView {
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mTaskIconAndName = findViewById(R.id.task_icon_and_name);
        mTaskName = findViewById(R.id.task_name);
        mTaskIcon = findViewById(R.id.task_icon);
        mOptionLayout = findViewById(R.id.menu_option_layout);
    }

@@ -112,6 +140,15 @@ public class TaskMenuView extends AbstractFloatingView {
        // TODO
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();

        // Remove all scale listeners when menu is removed
        mTaskView.getIconView().removeUpdateScaleListener(mTaskViewIconScaleListener);
        mTaskIcon.removeUpdateScaleListener(mMenuIconScaleListener);
    }

    @Override
    protected boolean isOfType(int type) {
        return (type & TYPE_TASK_MENU) != 0;
@@ -138,17 +175,21 @@ public class TaskMenuView extends AbstractFloatingView {

    private void addMenuOptions(TaskView taskView) {
        Drawable icon = taskView.getTask().icon.getConstantState().newDrawable();
        int iconSize = getResources().getDimensionPixelSize(R.dimen.task_thumbnail_icon_size);
        icon.setBounds(0, 0, iconSize, iconSize);
        mTaskIconAndName.setCompoundDrawables(null, icon, null, null);
        mTaskIconAndName.setText(TaskUtils.getTitle(getContext(), taskView.getTask()));
        mTaskIconAndName.setOnClickListener(v -> close(true));
        mTaskIcon.setDrawable(icon);
        mTaskIcon.setOnClickListener(v -> close(true));
        mTaskName.setText(TaskUtils.getTitle(getContext(), taskView.getTask()));
        mTaskName.setOnClickListener(v -> close(true));

        // Set the icons to match scale by listening to each other's changes
        mMenuIconDrawable = icon instanceof FastBitmapDrawable ? (FastBitmapDrawable) icon : null;
        taskView.getIconView().addUpdateScaleListener(mTaskViewIconScaleListener);
        mTaskIcon.addUpdateScaleListener(mMenuIconScaleListener);

        // Move the icon and text up half an icon size to lay over the TaskView
        LinearLayout.LayoutParams params =
                (LinearLayout.LayoutParams) mTaskIconAndName.getLayoutParams();
                (LinearLayout.LayoutParams) mTaskIcon.getLayoutParams();
        params.topMargin = (int) -getResources().getDimension(R.dimen.task_thumbnail_top_margin);
        mTaskIconAndName.setLayoutParams(params);
        mTaskIcon.setLayoutParams(params);

        for (TaskSystemShortcut menuOption : MENU_OPTIONS) {
            OnClickListener onClickListener = menuOption.getOnClickListener(mActivity, taskView);
+14 −1
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ public class FastBitmapDrawable extends Drawable {

    @Override
    public final void draw(Canvas canvas) {
        if (mScaleAnimation != null) {
        if (mScale != 1f) {
            int count = canvas.save();
            Rect bounds = getBounds();
            canvas.scale(mScale, mScale, bounds.exactCenterX(), bounds.exactCenterY());
@@ -150,10 +150,23 @@ public class FastBitmapDrawable extends Drawable {
        return mAlpha;
    }

    public void setScale(float scale) {
        if (mScaleAnimation != null) {
            mScaleAnimation.cancel();
            mScaleAnimation = null;
        }
        mScale = scale;
        invalidateSelf();
    }

    public float getAnimatedScale() {
        return mScaleAnimation == null ? 1 : mScale;
    }

    public float getScale() {
        return mScale;
    }

    @Override
    public int getIntrinsicWidth() {
        return mBitmap.getWidth();