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
This commit is contained in:
24
packages/SystemUI/res/drawable/recents_info_dark.xml
Normal file
24
packages/SystemUI/res/drawable/recents_info_dark.xml
Normal file
@@ -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>
|
||||
24
packages/SystemUI/res/drawable/recents_info_light.xml
Normal file
24
packages/SystemUI/res/drawable/recents_info_light.xml
Normal file
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
@@ -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" />
|
||||
@@ -144,7 +144,6 @@ public class RecentsHistoryAdapter extends RecyclerView.Adapter<RecentsHistoryAd
|
||||
|
||||
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;
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user