Adding reveal transition to show app-overlay.
- Instead of long-pressing the icon to launch into app info directly,
this will mirror notifications and reveal a space that can show the
app name and a link to app info.
Change-Id: I91c5839719b030a65744f5e677a436e9c719c578
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 0000000..b1a2242
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_info_dark.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48.0dp"
+ android:height="48.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="@color/recents_task_bar_dark_icon_color"
+ android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM13.000000,17.000000l-2.000000,0.000000l0.000000,-6.000000l2.000000,0.000000L13.000000,17.000000zM13.000000,9.000000l-2.000000,0.000000L11.000000,7.000000l2.000000,0.000000L13.000000,9.000000z"/>
+</vector>
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 0000000..bc58c3b
--- /dev/null
+++ b/packages/SystemUI/res/drawable/recents_info_light.xml
@@ -0,0 +1,24 @@
+<!--
+Copyright (C) 2014 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48.0dp"
+ android:height="48.0dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M12.000000,2.000000C6.500000,2.000000 2.000000,6.500000 2.000000,12.000000s4.500000,10.000000 10.000000,10.000000c5.500000,0.000000 10.000000,-4.500000 10.000000,-10.000000S17.500000,2.000000 12.000000,2.000000zM13.000000,17.000000l-2.000000,0.000000l0.000000,-6.000000l2.000000,0.000000L13.000000,17.000000zM13.000000,9.000000l-2.000000,0.000000L11.000000,7.000000l2.000000,0.000000L13.000000,9.000000z"
+ android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index 07ac39a..a94e781 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" />
- <ProgressBar
- android:id="@+id/focus_timer_indicator"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="match_parent"
- android:layout_height="5dp"
- android:layout_gravity="bottom"
- android:indeterminateOnly="false"
- android:visibility="invisible" />
+
+ <!-- The progress indicator shows if auto-paging is enabled -->
+ <ViewStub android:id="@+id/focus_timer_indicator_stub"
+ android:inflatedId="@+id/focus_timer_indicator"
+ android:layout="@layout/recents_task_view_header_progress_bar"
+ android:layout_width="match_parent"
+ android:layout_height="5dp"
+ android:layout_gravity="bottom" />
+
+ <!-- The app overlay shows as the user long-presses on the app icon -->
+ <ViewStub android:id="@+id/app_overlay_stub"
+ android:inflatedId="@+id/app_overlay"
+ android:layout="@layout/recents_task_view_header_overlay"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
</com.android.systemui.recents.views.TaskViewHeader>
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 0000000..5cdde9e
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<FrameLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone">
+ <com.android.systemui.recents.views.FixedSizeImageView
+ android:id="@+id/app_icon"
+ android:contentDescription="@string/recents_app_info_button_label"
+ android:layout_width="@dimen/recents_task_view_application_icon_size"
+ android:layout_height="@dimen/recents_task_view_application_icon_size"
+ android:layout_marginStart="8dp"
+ android:layout_gravity="center_vertical|start"
+ android:padding="8dp" />
+ <TextView
+ android:id="@+id/app_title"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|start"
+ android:layout_marginStart="64dp"
+ android:layout_marginEnd="112dp"
+ android:textSize="16sp"
+ android:textColor="#ffffffff"
+ android:text="@string/recents_empty_message"
+ android:fontFamily="sans-serif-medium"
+ android:singleLine="true"
+ android:maxLines="2"
+ android:ellipsize="marquee"
+ android:fadingEdge="horizontal" />
+ <com.android.systemui.recents.views.FixedSizeImageView
+ android:id="@+id/app_info"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_marginEnd="4dp"
+ android:layout_gravity="center_vertical|end"
+ android:padding="12dp"
+ android:background="@drawable/recents_button_bg"
+ android:src="@drawable/recents_info_light" />
+</FrameLayout>
\ 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 0000000..e740458
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_task_view_header_progress_bar.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 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.
+-->
+<ProgressBar
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ style="?android:attr/progressBarStyleHorizontal"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:indeterminateOnly="false"
+ android:visibility="gone" />
\ 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 fe23fa0..f6655c7 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 @@
private Context mContext;
private LayoutInflater mLayoutInflater;
- private final List<Task> mTasks = new ArrayList<>();
private final List<Row> 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 adc1e92..3f52ae8 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.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 @@
}
}
- /** 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,
@@ -610,6 +613,22 @@
}
/**
+ * 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.
*/
public Drawable getBadgedTaskDescriptionIcon(ActivityManager.TaskDescription taskDescription,
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 4bc42ea..9cdd703 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 @@
// 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 8d8fec6..44ad239 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 @@
// 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 @@
* 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 @@
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 a314ae2..809d4ee 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 @@
// 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 ba0fc8f..1f8216f 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 @@
/** 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 15cb14a..2563190 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.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 @@
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 @@
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 @@
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 @@
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 @@
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);
}
/**
@@ -275,11 +299,6 @@
}
@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 @@
/** 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 @@
/** 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 @@
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 @@
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 @@
@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 @@
: 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();
+ }
+ }
}