Merge "Add task content animation property" into ub-launcher3-master
diff --git a/go/quickstep/src/com/android/quickstep/TaskAdapter.java b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
index 674fcae..66c074b 100644
--- a/go/quickstep/src/com/android/quickstep/TaskAdapter.java
+++ b/go/quickstep/src/com/android/quickstep/TaskAdapter.java
@@ -94,7 +94,7 @@
return;
}
Task task = tasks.get(position);
- holder.bindTask(task);
+ holder.bindTask(task, false /* willAnimate */);
mLoader.loadTaskIconAndLabel(task, () -> {
// Ensure holder still has the same task.
if (Objects.equals(task, holder.getTask())) {
@@ -110,6 +110,13 @@
}
@Override
+ public void onBindViewHolder(@NonNull TaskHolder holder, int position,
+ @NonNull List<Object> payloads) {
+ // TODO: Bind task in preparation for animation. For now, we apply UI changes immediately.
+ super.onBindViewHolder(holder, position, payloads);
+ }
+
+ @Override
public void onViewAttachedToWindow(@NonNull TaskHolder holder) {
if (holder.getTask() == null) {
return;
diff --git a/go/quickstep/src/com/android/quickstep/TaskHolder.java b/go/quickstep/src/com/android/quickstep/TaskHolder.java
index 98dc989..91a3534 100644
--- a/go/quickstep/src/com/android/quickstep/TaskHolder.java
+++ b/go/quickstep/src/com/android/quickstep/TaskHolder.java
@@ -15,6 +15,9 @@
*/
package com.android.quickstep;
+import android.graphics.Bitmap;
+
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
@@ -40,13 +43,28 @@
}
/**
- * Bind a task to the holder, resetting the view and preparing it for content to load in.
+ * Bind the task model to the holder. This will take the current task content in the task
+ * object (i.e. icon, thumbnail, label) and either apply the content immediately or simply bind
+ * the content to animate to at a later time. If the task does not have all its content loaded,
+ * the view will prepare appropriate default placeholders and it is the callers responsibility
+ * to change them at a later time.
+ *
+ * Regardless of whether it is animating, input handlers will be bound immediately (see
+ * {@link TaskActionController}).
*
* @param task the task to bind to the view
+ * @param willAnimate true if UI should animate in later, false if it should apply immediately
*/
- public void bindTask(Task task) {
+ public void bindTask(@NonNull Task task, boolean willAnimate) {
mTask = task;
- mTaskItemView.resetTaskItemView();
+ Bitmap thumbnail = (task.thumbnail != null) ? task.thumbnail.thumbnail : null;
+ if (willAnimate) {
+ mTaskItemView.startContentAnimation(task.icon, thumbnail, task.titleDescription);
+ } else {
+ mTaskItemView.setIcon(task.icon);
+ mTaskItemView.setThumbnail(thumbnail);
+ mTaskItemView.setLabel(task.titleDescription);
+ }
}
/**
diff --git a/go/quickstep/src/com/android/quickstep/views/TaskItemView.java b/go/quickstep/src/com/android/quickstep/views/TaskItemView.java
index 0a3fba8..a8fc78a 100644
--- a/go/quickstep/src/com/android/quickstep/views/TaskItemView.java
+++ b/go/quickstep/src/com/android/quickstep/views/TaskItemView.java
@@ -21,6 +21,7 @@
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
+import android.util.FloatProperty;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -39,15 +40,37 @@
private static final String DEFAULT_LABEL = "...";
private final Drawable mDefaultIcon;
private final Drawable mDefaultThumbnail;
+ private final TaskLayerDrawable mIconDrawable;
+ private final TaskLayerDrawable mThumbnailDrawable;
private TextView mLabelView;
private ImageView mIconView;
private ImageView mThumbnailView;
+ private float mContentTransitionProgress;
+
+ /**
+ * Property representing the content transition progress of the view. 1.0f represents that the
+ * currently bound icon, thumbnail, and label are fully animated in and visible.
+ */
+ public static FloatProperty CONTENT_TRANSITION_PROGRESS =
+ new FloatProperty<TaskItemView>("taskContentTransitionProgress") {
+ @Override
+ public void setValue(TaskItemView view, float progress) {
+ view.setContentTransitionProgress(progress);
+ }
+
+ @Override
+ public Float get(TaskItemView view) {
+ return view.mContentTransitionProgress;
+ }
+ };
public TaskItemView(Context context, AttributeSet attrs) {
super(context, attrs);
Resources res = context.getResources();
mDefaultIcon = res.getDrawable(android.R.drawable.sym_def_app_icon, context.getTheme());
mDefaultThumbnail = res.getDrawable(R.drawable.default_thumbnail, context.getTheme());
+ mIconDrawable = new TaskLayerDrawable(context);
+ mThumbnailDrawable = new TaskLayerDrawable(context);
}
@Override
@@ -56,6 +79,12 @@
mLabelView = findViewById(R.id.task_label);
mThumbnailView = findViewById(R.id.task_thumbnail);
mIconView = findViewById(R.id.task_icon);
+
+ mThumbnailView.setImageDrawable(mThumbnailDrawable);
+ mIconView.setImageDrawable(mIconDrawable);
+
+ resetTaskItemView();
+ CONTENT_TRANSITION_PROGRESS.setValue(this, 1.0f);
}
/**
@@ -74,6 +103,7 @@
*/
public void setLabel(@Nullable String label) {
mLabelView.setText(getSafeLabel(label));
+ // TODO: Animation for label
}
/**
@@ -86,7 +116,7 @@
// The icon proper is actually smaller than the drawable and has "padding" on the side for
// the purpose of drawing the shadow, allowing the icon to pop up, so we need to scale the
// view if we want the icon to be flush with the bottom of the thumbnail.
- mIconView.setImageDrawable(getSafeIcon(icon));
+ mIconDrawable.setCurrentDrawable(getSafeIcon(icon));
}
/**
@@ -95,13 +125,38 @@
* @param thumbnail task thumbnail for the task
*/
public void setThumbnail(@Nullable Bitmap thumbnail) {
- mThumbnailView.setImageDrawable(getSafeThumbnail(thumbnail));
+ mThumbnailDrawable.setCurrentDrawable(getSafeThumbnail(thumbnail));
}
public View getThumbnailView() {
return mThumbnailView;
}
+ /**
+ * Start a new animation from the current task content to the specified new content. The caller
+ * is responsible for the actual animation control via the property
+ * {@link #CONTENT_TRANSITION_PROGRESS}.
+ *
+ * @param endIcon the icon to animate to
+ * @param endThumbnail the thumbnail to animate to
+ * @param endLabel the label to animate to
+ */
+ public void startContentAnimation(@Nullable Drawable endIcon, @Nullable Bitmap endThumbnail,
+ @Nullable String endLabel) {
+ mIconDrawable.startNewTransition(getSafeIcon(endIcon));
+ mThumbnailDrawable.startNewTransition(getSafeThumbnail(endThumbnail));
+ // TODO: Animation for label
+
+ setContentTransitionProgress(0.0f);
+ }
+
+ private void setContentTransitionProgress(float progress) {
+ mContentTransitionProgress = progress;
+ mIconDrawable.setTransitionProgress(progress);
+ mThumbnailDrawable.setTransitionProgress(progress);
+ // TODO: Animation for label
+ }
+
private @NonNull Drawable getSafeIcon(@Nullable Drawable icon) {
return (icon != null) ? icon : mDefaultIcon;
}