diff --git a/packages/SystemUI/res/drawable/recents_info_dark.xml b/packages/SystemUI/res/drawable/recents_info_dark.xml
new file mode 100644
index 0000000000000..b1a22425ef2d8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_info_dark.xml
@@ -0,0 +1,24 @@
+
+
+
+
diff --git a/packages/SystemUI/res/drawable/recents_info_light.xml b/packages/SystemUI/res/drawable/recents_info_light.xml
new file mode 100644
index 0000000000000..bc58c3b406d3f
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_info_light.xml
@@ -0,0 +1,24 @@
+
+
+
+
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index 07ac39a3eceae..a94e781d4a8d0 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -64,12 +64,19 @@
android:background="@drawable/recents_button_bg"
android:visibility="invisible"
android:src="@drawable/recents_dismiss_light" />
-
+
+
+
+
+
+
diff --git a/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml b/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
new file mode 100644
index 0000000000000..5cdde9e396d0c
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_task_view_header_progress_bar.xml b/packages/SystemUI/res/layout/recents_task_view_header_progress_bar.xml
new file mode 100644
index 0000000000000..e740458728dd7
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_task_view_header_progress_bar.xml
@@ -0,0 +1,22 @@
+
+
+
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
index fe23fa07c1e68..f6655c7f86a2a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -144,7 +144,6 @@ public class RecentsHistoryAdapter extends RecyclerView.Adapter mTasks = new ArrayList<>();
private final List mRows = new ArrayList<>();
private final SparseIntArray mTaskRowCount = new SparseIntArray();
private TaskStack mStack;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index adc1e9200daa4..3f52ae8d7ed15 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -30,6 +30,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
@@ -554,39 +555,41 @@ public class SystemServicesProxy {
}
}
- /** Returns the activity label */
- public String getActivityLabel(ActivityInfo info) {
+ /**
+ * Returns the activity label, badging if necessary.
+ */
+ public String getBadgedActivityLabel(ActivityInfo info, int userId) {
if (mPm == null) return null;
// If we are mocking, then return a mock label
if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
- return "Recent Task";
+ return "Recent Task: " + userId;
}
- return info.loadLabel(mPm).toString();
+ return getBadgedLabel(info.loadLabel(mPm).toString(), userId);
}
- /** Returns the application label */
- public String getApplicationLabel(Intent baseIntent, int userId) {
+ /**
+ * Returns the application label, badging if necessary.
+ */
+ public String getBadgedApplicationLabel(ApplicationInfo appInfo, int userId) {
if (mPm == null) return null;
// If we are mocking, then return a mock label
if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
- return "Recent Task";
+ return "Recent Task App: " + userId;
}
- ResolveInfo ri = mPm.resolveActivityAsUser(baseIntent, 0, userId);
- CharSequence label = (ri != null) ? ri.loadLabel(mPm) : null;
- return (label != null) ? label.toString() : null;
+ return getBadgedLabel(appInfo.loadLabel(mPm).toString(), userId);
}
- /** Returns the content description for a given task */
- public String getContentDescription(Intent baseIntent, int userId, String activityLabel,
- Resources res) {
- String applicationLabel = getApplicationLabel(baseIntent, userId);
- if (applicationLabel == null) {
- return getBadgedLabel(activityLabel, userId);
- }
+ /**
+ * Returns the content description for a given task, badging it if necessary. The content
+ * description joins the app and activity labels.
+ */
+ public String getBadgedContentDescription(ActivityInfo info, int userId, Resources res) {
+ String activityLabel = info.loadLabel(mPm).toString();
+ String applicationLabel = info.applicationInfo.loadLabel(mPm).toString();
String badgedApplicationLabel = getBadgedLabel(applicationLabel, userId);
return applicationLabel.equals(activityLabel) ? badgedApplicationLabel
: res.getString(R.string.accessibility_recents_task_header,
@@ -609,6 +612,22 @@ public class SystemServicesProxy {
return getBadgedIcon(icon, userId);
}
+ /**
+ * Returns the application icon for the ApplicationInfo for a user, badging if
+ * necessary.
+ */
+ public Drawable getBadgedApplicationIcon(ApplicationInfo appInfo, int userId) {
+ if (mPm == null) return null;
+
+ // If we are mocking, then return a mock label
+ if (RecentsDebugFlags.Static.EnableSystemServicesProxy) {
+ return new ColorDrawable(0xFF666666);
+ }
+
+ Drawable icon = appInfo.loadIcon(mPm);
+ return getBadgedIcon(icon, userId);
+ }
+
/**
* Returns the task description icon, loading and badging it if it necessary.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 4bc42ea823538..9cdd703852fe3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -162,7 +162,7 @@ public class RecentsTaskLoadPlan {
// Load the title, icon, and color
String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
- String contentDescription = loader.getAndUpdateContentDescription(taskKey, title, res);
+ String contentDescription = loader.getAndUpdateContentDescription(taskKey, res);
String dismissDescription = String.format(dismissDescFormat, contentDescription);
Drawable icon = isStackTask
? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
index 8d8fec632ef9b..44ad2397bd655 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoader.java
@@ -436,7 +436,7 @@ public class RecentsTaskLoader {
// All short paths failed, load the label from the activity info and cache it
ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey);
if (activityInfo != null) {
- label = ssp.getActivityLabel(activityInfo);
+ label = ssp.getBadgedActivityLabel(activityInfo, taskKey.userId);
mActivityLabelCache.put(taskKey, label);
return label;
}
@@ -449,8 +449,7 @@ public class RecentsTaskLoader {
* Returns the cached task content description if the task key is not expired, updating the
* cache if it is.
*/
- String getAndUpdateContentDescription(Task.TaskKey taskKey, String activityLabel,
- Resources res) {
+ String getAndUpdateContentDescription(Task.TaskKey taskKey, Resources res) {
SystemServicesProxy ssp = Recents.getSystemServices();
// Return the cached content description if it exists
@@ -458,13 +457,11 @@ public class RecentsTaskLoader {
if (label != null) {
return label;
}
- // If the given activity label is empty, don't compute or cache the content description
- if (activityLabel.isEmpty()) {
- return "";
- }
- label = ssp.getContentDescription(taskKey.baseIntent, taskKey.userId, activityLabel, res);
- if (label != null) {
+ // All short paths failed, load the label from the activity info and cache it
+ ActivityInfo activityInfo = getAndUpdateActivityInfo(taskKey);
+ if (activityInfo != null) {
+ label = ssp.getBadgedContentDescription(activityInfo, taskKey.userId, res);
mContentDescriptionCache.put(taskKey, label);
return label;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index a314ae2f90213..809d4eed7a116 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -1549,7 +1549,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Poke the doze trigger on user interaction
mUIDozeTrigger.poke();
if (event.showTimerIndicator && mFocusedTask != null) {
- getChildViewForTask(mFocusedTask).getHeaderView().cancelFocusTimerIndicator();
+ TaskView tv = getChildViewForTask(mFocusedTask);
+ if (tv != null) {
+ tv.getHeaderView().cancelFocusTimerIndicator();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index ba0fc8f017690..1f8216ffd750d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -162,6 +162,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Resets this TaskView for reuse. */
void reset() {
+ mHeaderView.reset();
resetViewProperties();
resetNoUserInteractionState();
setClipViewInStack(false);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 15cb14a15c4b7..2563190047f22 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -16,22 +16,27 @@
package com.android.systemui.recents.views;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
-import android.graphics.PorterDuff;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
-import android.graphics.drawable.RippleDrawable;
-import android.support.v4.graphics.ColorUtils;
import android.os.CountDownTimer;
+import android.support.v4.graphics.ColorUtils;
import android.util.AttributeSet;
import android.view.View;
+import android.view.ViewAnimationUtils;
+import android.view.ViewStub;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
@@ -39,10 +44,10 @@ import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.android.internal.logging.MetricsLogger;
-
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.Recents;
+import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.ui.ShowApplicationInfoEvent;
@@ -59,6 +64,8 @@ public class TaskViewHeader extends FrameLayout
implements View.OnClickListener, View.OnLongClickListener {
private static final float HIGHLIGHT_LIGHTNESS_INCREMENT = 0.125f;
+ private static final float OVERLAY_LIGHTNESS_INCREMENT = -0.0625f;
+ private static final int OVERLAY_REVEAL_DURATION = 250;
private static final long FOCUS_INDICATOR_INTERVAL_MS = 30;
/**
@@ -69,8 +76,6 @@ public class TaskViewHeader extends FrameLayout
private Paint mHighlightPaint = new Paint();
private Paint mBackgroundPaint = new Paint();
- private float[] mTmpHSL = new float[3];
-
public HighlightColorDrawable() {
mBackgroundPaint.setColor(Color.argb(255, 0, 0, 0));
mBackgroundPaint.setAntiAlias(true);
@@ -122,11 +127,16 @@ public class TaskViewHeader extends FrameLayout
Task mTask;
// Header views
- ImageView mMoveTaskButton;
- ImageView mDismissButton;
ImageView mIconView;
TextView mTitleView;
- int mMoveTaskTargetStackId = INVALID_STACK_ID;
+ ImageView mMoveTaskButton;
+ ImageView mDismissButton;
+ ViewStub mAppOverlayViewStub;
+ FrameLayout mAppOverlayView;
+ ImageView mAppIconView;
+ ImageView mAppInfoView;
+ TextView mAppTitleView;
+ ViewStub mFocusTimerIndicatorStub;
ProgressBar mFocusTimerIndicator;
// Header drawables
@@ -140,21 +150,26 @@ public class TaskViewHeader extends FrameLayout
Drawable mDarkFreeformIcon;
Drawable mLightFullscreenIcon;
Drawable mDarkFullscreenIcon;
+ Drawable mLightInfoIcon;
+ Drawable mDarkInfoIcon;
int mTaskBarViewLightTextColor;
int mTaskBarViewDarkTextColor;
+ int mMoveTaskTargetStackId = INVALID_STACK_ID;
// Header background
private HighlightColorDrawable mBackground;
+ private HighlightColorDrawable mOverlayBackground;
+ private float[] mTmpHSL = new float[3];
// Header dim, which is only used when task view hardware layers are not used
private Paint mDimLayerPaint = new Paint();
Interpolator mFastOutSlowInInterpolator;
Interpolator mFastOutLinearInInterpolator;
+ Interpolator mLinearOutSlowInInterpolator;
- long mFocusIndicatorProgress;
private CountDownTimer mFocusTimerCountDown;
- long mFocusTimerDuration;
+ private long mFocusTimerDuration;
public TaskViewHeader(Context context) {
this(context, null);
@@ -184,36 +199,45 @@ public class TaskViewHeader extends FrameLayout
mDarkFreeformIcon = context.getDrawable(R.drawable.recents_move_task_freeform_dark);
mLightFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_light);
mDarkFullscreenIcon = context.getDrawable(R.drawable.recents_move_task_fullscreen_dark);
+ mLightInfoIcon = context.getDrawable(R.drawable.recents_info_light);
+ mDarkInfoIcon = context.getDrawable(R.drawable.recents_info_dark);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_linear_in);
+ mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
+ com.android.internal.R.interpolator.linear_out_slow_in);
// Configure the background and dim
mBackground = new HighlightColorDrawable();
mBackground.setColorAndDim(Color.argb(255, 0, 0, 0), 0f);
setBackground(mBackground);
+ mOverlayBackground = new HighlightColorDrawable();
mDimLayerPaint.setColor(Color.argb(255, 0, 0, 0));
mDimLayerPaint.setAntiAlias(true);
mFocusTimerDuration = res.getInteger(R.integer.recents_auto_advance_duration);
}
+ /**
+ * Resets this header along with the TaskView.
+ */
+ public void reset() {
+ hideAppOverlay(true /* immediate */);
+ }
+
@Override
protected void onFinishInflate() {
// Initialize the icon and description views
mIconView = (ImageView) findViewById(R.id.icon);
+ mIconView.setClickable(false);
mIconView.setOnLongClickListener(this);
mTitleView = (TextView) findViewById(R.id.title);
mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
mDismissButton.setOnClickListener(this);
mMoveTaskButton = (ImageView) findViewById(R.id.move_task);
- mFocusTimerIndicator = (ProgressBar) findViewById(R.id.focus_timer_indicator);
-
- // Hide the backgrounds if they are ripple drawables
- if (mIconView.getBackground() instanceof RippleDrawable) {
- mIconView.setBackground(null);
- }
+ mFocusTimerIndicatorStub = (ViewStub) findViewById(R.id.focus_timer_indicator_stub);
+ mAppOverlayViewStub = (ViewStub) findViewById(R.id.app_overlay_stub);
}
/**
@@ -274,11 +298,6 @@ public class TaskViewHeader extends FrameLayout
invalidate();
}
- @Override
- protected boolean verifyDrawable(Drawable who) {
- return super.verifyDrawable(who) || (who == mBackground);
- }
-
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
@@ -290,6 +309,10 @@ public class TaskViewHeader extends FrameLayout
/** Starts the focus timer. */
public void startFocusTimerIndicator() {
+ if (mFocusTimerIndicator == null) {
+ return;
+ }
+
mFocusTimerIndicator.setVisibility(View.VISIBLE);
mFocusTimerIndicator.setMax((int) mFocusTimerDuration);
if (mFocusTimerCountDown == null) {
@@ -310,7 +333,11 @@ public class TaskViewHeader extends FrameLayout
/** Cancels the focus timer. */
public void cancelFocusTimerIndicator() {
- if (mFocusTimerCountDown != null && mFocusTimerIndicator != null) {
+ if (mFocusTimerIndicator == null) {
+ return;
+ }
+
+ if (mFocusTimerCountDown != null) {
mFocusTimerCountDown.cancel();
mFocusTimerIndicator.setProgress(0);
mFocusTimerIndicator.setVisibility(View.INVISIBLE);
@@ -339,6 +366,10 @@ public class TaskViewHeader extends FrameLayout
private void updateBackgroundColor(float dimAlpha) {
if (mTask != null) {
mBackground.setColorAndDim(mTask.colorPrimary, dimAlpha);
+ // TODO: Consider using the saturation of the color to adjust the lightness as well
+ ColorUtils.colorToHSL(mTask.colorPrimary, mTmpHSL);
+ mTmpHSL[2] = Math.min(1f, mTmpHSL[2] + OVERLAY_LIGHTNESS_INCREMENT * (1.0f - dimAlpha));
+ mOverlayBackground.setColorAndDim(ColorUtils.HSLToColor(mTmpHSL), dimAlpha);
mDimLayerPaint.setAlpha((int) (dimAlpha * 255));
}
}
@@ -384,10 +415,15 @@ public class TaskViewHeader extends FrameLayout
mMoveTaskButton.setOnClickListener(this);
}
- mFocusTimerIndicator.getProgressDrawable()
- .setColorFilter(
- getSecondaryColor(t.colorPrimary, t.useLightOnPrimaryColor),
- PorterDuff.Mode.SRC_IN);
+ if (Recents.getDebugFlags().isFastToggleIndicatorEnabled()) {
+ if (mFocusTimerIndicator == null) {
+ mFocusTimerIndicator = (ProgressBar) mFocusTimerIndicatorStub.inflate();
+ }
+ mFocusTimerIndicator.getProgressDrawable()
+ .setColorFilter(
+ getSecondaryColor(t.colorPrimary, t.useLightOnPrimaryColor),
+ PorterDuff.Mode.SRC_IN);
+ }
// In accessibility, a single click on the focused app info button will show it
if (ssp.isTouchExplorationEnabled()) {
@@ -449,8 +485,11 @@ public class TaskViewHeader extends FrameLayout
@Override
public void onClick(View v) {
if (v == mIconView) {
- // In accessibility, a single click on the focused app info button will show it
- EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ if (ssp.isTouchExplorationEnabled()) {
+ // In accessibility, a single click on the focused app info button will show it
+ EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
+ }
} else if (v == mDismissButton) {
TaskView tv = Utilities.findParent(this, TaskView.class);
tv.dismissTask();
@@ -465,15 +504,92 @@ public class TaskViewHeader extends FrameLayout
: new Rect();
EventBus.getDefault().send(new LaunchTaskEvent(tv, mTask, bounds,
mMoveTaskTargetStackId, false));
+ } else if (v == mAppInfoView) {
+ EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
+ } else if (v == mAppIconView) {
+ hideAppOverlay(false /* immediate */);
}
}
@Override
public boolean onLongClick(View v) {
if (v == mIconView) {
- EventBus.getDefault().send(new ShowApplicationInfoEvent(mTask));
+ showAppOverlay();
+ return true;
+ } else if (v == mAppIconView) {
+ hideAppOverlay(false /* immediate */);
return true;
}
return false;
}
+
+ /**
+ * Shows the application overlay.
+ */
+ private void showAppOverlay() {
+ // Skip early if the task is invalid
+ SystemServicesProxy ssp = Recents.getSystemServices();
+ ComponentName cn = mTask.key.getComponent();
+ int userId = mTask.key.userId;
+ ActivityInfo activityInfo = ssp.getActivityInfo(cn, userId);
+ if (activityInfo == null) {
+ return;
+ }
+
+ // Inflate the overlay if necessary
+ if (mAppOverlayView == null) {
+ mAppOverlayView = (FrameLayout) mAppOverlayViewStub.inflate();
+ mAppOverlayView.setBackground(mOverlayBackground);
+ mAppIconView = (ImageView) mAppOverlayView.findViewById(R.id.app_icon);
+ mAppIconView.setOnClickListener(this);
+ mAppIconView.setOnLongClickListener(this);
+ mAppInfoView = (ImageView) mAppOverlayView.findViewById(R.id.app_info);
+ mAppInfoView.setOnClickListener(this);
+ mAppTitleView = (TextView) mAppOverlayView.findViewById(R.id.app_title);
+ }
+
+ // Update the overlay contents for the current app
+ mAppTitleView.setText(ssp.getBadgedApplicationLabel(activityInfo.applicationInfo, userId));
+ mAppIconView.setImageDrawable(ssp.getBadgedApplicationIcon(activityInfo.applicationInfo, userId));
+ mAppInfoView.setImageDrawable(mTask.useLightOnPrimaryColor
+ ? mLightInfoIcon
+ : mDarkInfoIcon);
+ mAppOverlayView.setVisibility(View.VISIBLE);
+
+ int x = mIconView.getLeft() + mIconView.getWidth() / 2;
+ int y = mIconView.getTop() + mIconView.getHeight() / 2;
+ Animator revealAnim = ViewAnimationUtils.createCircularReveal(mAppOverlayView, x, y, 0,
+ getWidth());
+ revealAnim.setDuration(OVERLAY_REVEAL_DURATION);
+ revealAnim.setInterpolator(mLinearOutSlowInInterpolator);
+ revealAnim.start();
+ }
+
+ /**
+ * Hide the application overlay.
+ */
+ private void hideAppOverlay(boolean immediate) {
+ // Skip if we haven't even loaded the overlay yet
+ if (mAppOverlayView == null) {
+ return;
+ }
+
+ if (immediate) {
+ mAppOverlayView.setVisibility(View.GONE);
+ } else {
+ int x = mIconView.getLeft() + mIconView.getWidth() / 2;
+ int y = mIconView.getTop() + mIconView.getHeight() / 2;
+ Animator revealAnim = ViewAnimationUtils.createCircularReveal(mAppOverlayView, x, y,
+ getWidth(), 0);
+ revealAnim.setDuration(OVERLAY_REVEAL_DURATION);
+ revealAnim.setInterpolator(mLinearOutSlowInInterpolator);
+ revealAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAppOverlayView.setVisibility(View.GONE);
+ }
+ });
+ revealAnim.start();
+ }
+ }
}