Merge "Part 1: Tweaking history transition to match design."
diff --git a/packages/SystemUI/res/drawable/ic_history.xml b/packages/SystemUI/res/drawable/ic_history.xml
new file mode 100644
index 0000000..e936864
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_history.xml
@@ -0,0 +1,28 @@
+<?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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+
+ <path
+ android:fillColor="#FFFFFF"
+ android:pathData="M13 3c-4.97 0-9 4.03-9 9H1l3.89 3.89 .07 .14L9 12H6c0-3.87 3.13-7 7-7s7 3.13 7
+7-3.13 7-7 7c-1.93 0-3.68-.79-4.94-2.06l-1.42 1.42C8.27 19.99 10.51 21 13
+21c4.97 0 9-4.03 9-9s-4.03-9-9-9zm-1 5v5l4.28 2.54 .72 -1.21-3.5-2.08V8H12z" />
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents.xml b/packages/SystemUI/res/layout/recents.xml
index 16ff14c..186aaf6 100644
--- a/packages/SystemUI/res/layout/recents.xml
+++ b/packages/SystemUI/res/layout/recents.xml
@@ -17,14 +17,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <!-- Status Bar Scrim View -->
- <ImageView
- android:id="@+id/status_bar_scrim"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal|top"
- android:scaleType="fitXY"
- android:src="@drawable/recents_status_gradient" />
<!-- Recents View -->
<com.android.systemui.recents.views.RecentsView
@@ -33,12 +25,6 @@
android:layout_height="match_parent">
</com.android.systemui.recents.views.RecentsView>
- <!-- History View -->
- <ViewStub android:id="@+id/history_view_stub"
- android:layout="@layout/recents_history"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-
<!-- Nav Bar Scrim View -->
<ImageView
android:id="@+id/nav_bar_scrim"
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 4b68e77..b2c0331 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -24,5 +24,4 @@
android:textColor="#ffffffff"
android:text="@string/recents_empty_message"
android:fontFamily="sans-serif"
- android:background="#80000000"
android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_history.xml b/packages/SystemUI/res/layout/recents_history.xml
index b65a5c5..dc2da72 100644
--- a/packages/SystemUI/res/layout/recents_history.xml
+++ b/packages/SystemUI/res/layout/recents_history.xml
@@ -17,7 +17,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="#99000000"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
diff --git a/packages/SystemUI/res/layout/recents_history_button.xml b/packages/SystemUI/res/layout/recents_history_button.xml
index 8c96fc6..538bad1 100644
--- a/packages/SystemUI/res/layout/recents_history_button.xml
+++ b/packages/SystemUI/res/layout/recents_history_button.xml
@@ -15,15 +15,24 @@
-->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:id="@+id/button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:gravity="start|center_vertical"
- android:text="@string/recents_show_history_button_label"
+ android:paddingStart="14dp"
+ android:paddingEnd="14dp"
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp"
+ android:text="@string/recents_history_button_label"
android:textSize="14sp"
android:textColor="#FFFFFF"
android:textAllCaps="true"
+ android:drawableStart="@drawable/ic_history"
+ android:drawablePadding="6dp"
android:shadowColor="#99000000"
android:shadowDx="0"
android:shadowDy="2"
android:shadowRadius="5"
- android:fontFamily="sans-serif-medium" />
\ No newline at end of file
+ android:fontFamily="sans-serif-medium"
+ android:background="?android:selectableItemBackground"
+ android:visibility="invisible" />
diff --git a/packages/SystemUI/res/layout/recents_history_date.xml b/packages/SystemUI/res/layout/recents_history_date.xml
index 6d6a9ee..13c7dbe 100644
--- a/packages/SystemUI/res/layout/recents_history_date.xml
+++ b/packages/SystemUI/res/layout/recents_history_date.xml
@@ -15,10 +15,12 @@
-->
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:theme="@android:style/Theme.Material"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:padding="12dp"
+ android:paddingStart="4dp"
+ android:paddingEnd="4dp"
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp"
android:gravity="start"
android:textSize="14sp"
android:textColor="#009688"
diff --git a/packages/SystemUI/res/layout/recents_history_task.xml b/packages/SystemUI/res/layout/recents_history_task.xml
index ae11006..e92c24a 100644
--- a/packages/SystemUI/res/layout/recents_history_task.xml
+++ b/packages/SystemUI/res/layout/recents_history_task.xml
@@ -15,7 +15,6 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:theme="@android:style/Theme.Material"
android:layout_width="match_parent"
android:layout_height="48dp"
android:orientation="horizontal"
@@ -27,7 +26,8 @@
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center"
- android:layout_marginStart="16dp" />
+ android:layout_marginStart="4dp"
+ android:layout_marginEnd="12dp" />
<TextView
android:id="@+id/description"
android:layout_width="0dp"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a490635..b096934 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -715,9 +715,7 @@
<!-- Recents: Launch error string. [CHAR LIMIT=NONE] -->
<string name="recents_launch_error_message">Could not start <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
<!-- Recents: Show history string. [CHAR LIMIT=NONE] -->
- <string name="recents_show_history_button_label">More</string>
- <!-- Recents: A format string to set the number of availabe historical tasks in recents. [CHAR LIMIT=NONE] -->
- <string name="recents_history_label_format"><xliff:g id="number">%d</xliff:g> More</string>
+ <string name="recents_history_button_label">History</string>
<!-- Recents: MultiStack add stack split horizontal radio button. [CHAR LIMIT=NONE] -->
<string name="recents_multistack_add_stack_dialog_split_horizontal">Split Horizontal</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 4329f78..e40a0f4 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -20,7 +20,7 @@
<item name="android:windowAnimationStyle">@style/Animation.RecentsActivity</item>
</style>
- <style name="RecentsTheme" parent="@android:style/Theme.Material.Light">
+ <style name="RecentsTheme" parent="@android:style/Theme.Material">
<!-- NoTitle -->
<item name="android:windowNoTitle">true</item>
<!-- Misc -->
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index fa30eed..cd2c942 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -57,6 +57,7 @@
import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.ToggleHistoryEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
@@ -105,8 +106,6 @@
// Top level views
private RecentsView mRecentsView;
private SystemBarScrimViews mScrimViews;
- private ViewStub mHistoryViewStub;
- private RecentsHistoryView mHistoryView;
// Search AppWidget
private AppWidgetProviderInfo mSearchWidgetInfo;
@@ -127,12 +126,14 @@
* just finishing the activity since we don't know what is behind Recents in the task stack.
*/
class FinishRecentsRunnable implements Runnable {
+
Intent mLaunchIntent;
+ ActivityOptions mOpts;
/**
* Creates a finish runnable that starts the specified intent.
*/
- public FinishRecentsRunnable(Intent launchIntent) {
+ public FinishRecentsRunnable(Intent launchIntent, ActivityOptions opts) {
mLaunchIntent = launchIntent;
}
@@ -141,13 +142,16 @@
try {
RecentsActivityLaunchState launchState =
Recents.getConfiguration().getLaunchState();
- ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
- launchState.launchedFromSearchHome ?
- R.anim.recents_to_search_launcher_enter :
- R.anim.recents_to_launcher_enter,
- launchState.launchedFromSearchHome ?
- R.anim.recents_to_search_launcher_exit :
- R.anim.recents_to_launcher_exit);
+ ActivityOptions opts = mOpts;
+ if (opts == null) {
+ opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
+ launchState.launchedFromSearchHome ?
+ R.anim.recents_to_search_launcher_enter :
+ R.anim.recents_to_launcher_enter,
+ launchState.launchedFromSearchHome ?
+ R.anim.recents_to_search_launcher_exit :
+ R.anim.recents_to_launcher_exit);
+ }
startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
} catch (Exception e) {
Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
@@ -205,12 +209,9 @@
int launchTaskIndexInStack = launchTarget != null
? stack.indexOfStackTask(launchTarget)
: 0;
- boolean hasStatusBarScrim = taskCount > 0;
- boolean animateStatusBarScrim = launchState.launchedFromHome;
boolean hasNavBarScrim = (taskCount > 0) && !config.hasTransposedNavBar;
boolean animateNavBarScrim = true;
- mScrimViews.prepareEnterRecentsAnimation(hasStatusBarScrim, animateStatusBarScrim,
- hasNavBarScrim, animateNavBarScrim);
+ mScrimViews.prepareEnterRecentsAnimation(hasNavBarScrim, animateNavBarScrim);
// Keep track of whether we launched from the nav bar button or via alt-tab
if (launchState.launchedWithAltTab) {
@@ -234,8 +235,7 @@
* Dismisses the history view back into the stack view.
*/
boolean dismissHistory() {
- // Try and hide the history view first
- if (mHistoryView != null && mHistoryView.isVisible()) {
+ if (mRecentsView.isHistoryVisible()) {
EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
return true;
}
@@ -287,9 +287,24 @@
* Dismisses Recents directly to Home without checking whether it is currently visible.
*/
void dismissRecentsToHome(boolean animateTaskViews) {
+ dismissRecentsToHome(animateTaskViews, null);
+ }
+
+ /**
+ * Dismisses Recents directly to Home without checking whether it is currently visible.
+ *
+ * @param overrideAnimation If not null, will override the default animation that is based on
+ * how Recents was launched.
+ */
+ void dismissRecentsToHome(boolean animateTaskViews, ActivityOptions overrideAnimation) {
DismissRecentsToHomeAnimationStarted dismissEvent =
new DismissRecentsToHomeAnimationStarted(animateTaskViews);
- dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
+ if (overrideAnimation != null) {
+ dismissEvent.addPostAnimationCallback(new FinishRecentsRunnable(
+ mFinishLaunchHomeRunnable.mLaunchIntent, overrideAnimation));
+ } else {
+ dismissEvent.addPostAnimationCallback(mFinishLaunchHomeRunnable);
+ }
dismissEvent.addPostAnimationCallback(new Runnable() {
@Override
public void run() {
@@ -342,7 +357,6 @@
mRecentsView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
- mHistoryViewStub = (ViewStub) findViewById(R.id.history_view_stub);
mScrimViews = new SystemBarScrimViews(this);
getWindow().getAttributes().privateFlags |=
WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
@@ -360,7 +374,7 @@
homeIntent.addCategory(Intent.CATEGORY_HOME);
homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);
+ mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent, null);
// Bind the search app widget when we first start up
if (RecentsDebugFlags.Static.EnableSearchBar) {
@@ -441,7 +455,7 @@
// Reset some states
mIgnoreAltTabRelease = false;
- if (mHistoryView != null) {
+ if (mRecentsView.isHistoryVisible()) {
EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
}
@@ -503,8 +517,7 @@
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
- outState.putBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE,
- (mHistoryView != null) && mHistoryView.isVisible());
+ outState.putBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE, mRecentsView.isHistoryVisible());
}
@Override
@@ -651,15 +664,12 @@
}
} else if (event.triggeredFromHomeKey) {
// Otherwise, dismiss Recents to Home
- if (mHistoryView != null && mHistoryView.isVisible()) {
- HideHistoryEvent hideEvent = new HideHistoryEvent(true /* animate */);
- hideEvent.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- dismissRecentsToHome(true /* animateTaskViews */);
- }
- });
- EventBus.getDefault().send(hideEvent);
+ if (mRecentsView.isHistoryVisible()) {
+ // If the history view is visible, then just cross-fade home
+ ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
+ R.anim.recents_to_launcher_enter,
+ R.anim.recents_to_launcher_exit);
+ dismissRecentsToHome(false /* animate */, opts);
} else {
dismissRecentsToHome(true /* animateTaskViews */);
@@ -795,21 +805,6 @@
mIgnoreAltTabRelease = true;
}
- public final void onBusEvent(ShowHistoryEvent event) {
- if (mHistoryView == null) {
- mHistoryView = (RecentsHistoryView) mHistoryViewStub.inflate();
- // Since this history view is inflated by a view stub after the insets have already
- // been applied, we have to set them ourselves initial from the insets that were last
- // provided.
- mHistoryView.setSystemInsets(mRecentsView.getSystemInsets());
- }
- mHistoryView.show(mRecentsView.getTaskStack(), event.getAnimationTrigger());
- }
-
- public final void onBusEvent(HideHistoryEvent event) {
- mHistoryView.hide(event.animate, event.getAnimationTrigger());
- }
-
private void refreshSearchWidgetView() {
if (mSearchWidgetInfo != null) {
SystemServicesProxy ssp = Recents.getSystemServices();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
index af3eeb0..bacf3bd 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
@@ -21,7 +21,7 @@
/**
* This is sent when the history view will be closed.
*/
-public class HideHistoryEvent extends EventBus.AnimatedEvent {
+public class HideHistoryEvent extends EventBus.Event {
public final boolean animate;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
index 7042537..ae803ea 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
@@ -22,5 +22,11 @@
* This is sent when the history view button should be shown.
*/
public class ShowHistoryButtonEvent extends EventBus.Event {
- // Simple event
+
+ // Whether or not to translate the history button when showing it
+ public final boolean translate;
+
+ public ShowHistoryButtonEvent(boolean translate) {
+ this.translate = translate;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
index b39d645..469f336 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
@@ -21,7 +21,7 @@
/**
* This is sent when the history view button is clicked.
*/
-public class ShowHistoryEvent extends EventBus.AnimatedEvent {
+public class ShowHistoryEvent extends EventBus.Event {
// Simple event
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java
new file mode 100644
index 0000000..aaf77af
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents.events.activity;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent when the history view button is clicked.
+ */
+public class ToggleHistoryEvent extends EventBus.AnimatedEvent {
+
+ // Simple event
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java
new file mode 100644
index 0000000..863f40b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent to reset the background scrim back to the initial state.
+ */
+public class ResetBackgroundScrimEvent extends EventBus.Event {
+ // Simple event
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java
new file mode 100644
index 0000000..fdd4c67
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents.events.ui;
+
+import com.android.systemui.recents.events.EventBus;
+
+/**
+ * This is sent to request an update to the background scrim.
+ */
+public class UpdateBackgroundScrimEvent extends EventBus.Event {
+
+ public final float alpha;
+
+ public UpdateBackgroundScrimEvent(float alpha) {
+ this.alpha = alpha;
+ }
+}
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 4000991..2c28c29 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
@@ -166,14 +166,16 @@
final List<Task> tasksMostRecent = new ArrayList<>(stack.getHistoricalTasks());
Collections.reverse(tasksMostRecent);
int prevDateKey = -1;
+ int taskCount = tasksMostRecent.size();
mRows.clear();
mTaskRowCount.clear();
- for (Task task : tasksMostRecent) {
+ Calendar cal = Calendar.getInstance(l);
+ for (int i = 0; i < taskCount; i++) {
+ Task task = tasksMostRecent.get(i);
if (task.isFreeformTask()) {
continue;
}
- Calendar cal = Calendar.getInstance(l);
cal.setTimeInMillis(task.key.lastActiveTime);
int dateKey = Objects.hash(cal.get(Calendar.YEAR), cal.get(Calendar.DAY_OF_YEAR));
if (dateKey != prevDateKey) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
index b9921b6..6dd4b53 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.history;
+import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
@@ -37,22 +38,29 @@
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.PackagesChangedEvent;
+import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
+import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.views.AnimateableViewBounds;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
/**
* A list of the recent tasks that are not in the stack.
*/
-public class RecentsHistoryView extends LinearLayout {
+public class RecentsHistoryView extends LinearLayout
+ implements ValueAnimator.AnimatorUpdateListener {
- private static final String TAG = "RecentsHistoryView";
- private static final boolean DEBUG = false;
+ private static final float TRANSLATION_Y_PCT = 0.25f;
+ private static final float BG_SCRIM_ALPHA = 0.625f;
private RecyclerView mRecyclerView;
private RecentsHistoryAdapter mAdapter;
private RecentsHistoryItemTouchCallbacks mItemTouchHandler;
+ private AnimateableViewBounds mViewBounds;
private boolean mIsVisible;
private Rect mSystemInsets = new Rect();
+ private int mHeaderHeight;
private Interpolator mFastOutSlowInInterpolator;
private Interpolator mFastOutLinearInInterpolator;
@@ -81,27 +89,28 @@
com.android.internal.R.interpolator.fast_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_linear_in);
+ mViewBounds = new AnimateableViewBounds(this, 0);
+ setOutlineProvider(mViewBounds);
}
/**
* Updates this history view with the recent tasks, and then shows it.
*/
- public void show(TaskStack stack, ReferenceCountedTrigger postHideAnimationTrigger) {
+ public void show(TaskStack stack, int stackHeight) {
setVisibility(View.VISIBLE);
setAlpha(0f);
- postHideAnimationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- animate()
- .alpha(1f)
- .setDuration(mHistoryTransitionDuration)
- .setInterpolator(mFastOutSlowInInterpolator)
- .withLayer()
- .start();
- }
- });
+ setTranslationY(-stackHeight * TRANSLATION_Y_PCT);
+ animate()
+ .alpha(1f)
+ .translationY(0f)
+ .setDuration(mHistoryTransitionDuration)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .setUpdateListener(this)
+ .withLayer()
+ .start();
mAdapter.updateTasks(getContext(), stack);
mIsVisible = true;
+ EventBus.getDefault().send(new UpdateBackgroundScrimEvent(BG_SCRIM_ALPHA));
MetricsLogger.visible(mRecyclerView.getContext(), MetricsEvent.OVERVIEW_HISTORY);
}
@@ -109,31 +118,28 @@
/**
* Hides this history view.
*/
- public void hide(boolean animate, final ReferenceCountedTrigger postAnimationTrigger) {
+ public void hide(boolean animate, int stackHeight) {
if (animate) {
animate()
.alpha(0f)
+ .translationY(-stackHeight * TRANSLATION_Y_PCT)
.setDuration(mHistoryTransitionDuration)
.setInterpolator(mFastOutLinearInInterpolator)
+ .setUpdateListener(this)
.withEndAction(new Runnable() {
@Override
public void run() {
setVisibility(View.INVISIBLE);
- if (postAnimationTrigger != null) {
- postAnimationTrigger.decrement();
- }
}
})
.withLayer()
.start();
- if (postAnimationTrigger != null) {
- postAnimationTrigger.increment();
- }
} else {
setAlpha(0f);
setVisibility(View.INVISIBLE);
}
mIsVisible = false;
+ EventBus.getDefault().send(new ResetBackgroundScrimEvent());
MetricsLogger.hidden(mRecyclerView.getContext(), MetricsEvent.OVERVIEW_HISTORY);
}
@@ -142,7 +148,15 @@
* Updates the system insets of this history view to the provided values.
*/
public void setSystemInsets(Rect systemInsets) {
- mSystemInsets.set(systemInsets.left, systemInsets.top, systemInsets.right, systemInsets.bottom);
+ mSystemInsets.set(systemInsets);
+ requestLayout();
+ }
+
+ /**
+ * Updates the header height to account for the history button bar.
+ */
+ public void setHeaderHeight(int height) {
+ mHeaderHeight = height;
requestLayout();
}
@@ -177,7 +191,7 @@
int stackHeightPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_stack_top_padding);
mRecyclerView.setPadding(stackWidthPadding + mSystemInsets.left,
- stackHeightPadding + mSystemInsets.top,
+ stackHeightPadding + mSystemInsets.top + mHeaderHeight,
stackWidthPadding + mSystemInsets.right, mSystemInsets.bottom);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@@ -201,6 +215,13 @@
return insets;
}
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ // Clip the top of the view by the header bar height
+ int top = Math.max(0, (int) -getTranslationY()) + mSystemInsets.top + mHeaderHeight;
+ mViewBounds.setClipTop(top);
+ }
+
/**** EventBus Events ****/
public final void onBusEvent(PackagesChangedEvent event) {
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 d15828a..3029acf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -37,6 +37,7 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Formatter;
import java.util.List;
@@ -130,6 +131,7 @@
SparseIntArray affiliatedTaskCounts = new SparseIntArray();
String dismissDescFormat = mContext.getString(
R.string.accessibility_recents_item_will_be_dismissed);
+ Formatter dismissDescFormatter = new Formatter();
long lastStackActiveTime = Prefs.getLong(mContext,
Prefs.Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME, 0);
if (RecentsDebugFlags.Static.EnableMockTasks) {
@@ -168,7 +170,8 @@
// Load the title, icon, and color
String title = loader.getAndUpdateActivityTitle(taskKey, t.taskDescription);
String contentDescription = loader.getAndUpdateContentDescription(taskKey, res);
- String dismissDescription = String.format(dismissDescFormat, contentDescription);
+ String dismissDescription = dismissDescFormatter.format(dismissDescFormat,
+ contentDescription).toString();
Drawable icon = isStackTask
? loader.getAndUpdateActivityIcon(taskKey, t.taskDescription, res, false)
: null;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 5a72897..5842095 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -48,10 +48,16 @@
@Override
public void getOutline(View view, Outline outline) {
outline.setAlpha(mMinAlpha + mAlpha / (1f - mMinAlpha));
- outline.setRoundRect(mClipRect.left, mClipRect.top,
- mSourceView.getWidth() - mClipRect.right,
- mSourceView.getHeight() - mClipRect.bottom,
- mCornerRadius);
+ if (mCornerRadius > 0) {
+ outline.setRoundRect(mClipRect.left, mClipRect.top,
+ mSourceView.getWidth() - mClipRect.right,
+ mSourceView.getHeight() - mClipRect.bottom,
+ mCornerRadius);
+ } else {
+ outline.setRect(mClipRect.left, mClipRect.top,
+ mSourceView.getWidth() - mClipRect.right,
+ mSourceView.getHeight() - mClipRect.bottom);
+ }
}
/** Sets the view outline alpha. */
@@ -63,6 +69,17 @@
}
}
+ /** Sets the top clip. */
+ public void setClipTop(int top) {
+ mClipRect.top = top;
+ updateClipBounds();
+ }
+
+ /** Returns the top clip. */
+ public int getClipTop() {
+ return mClipRect.top;
+ }
+
/** Sets the bottom clip. */
public void setClipBottom(int bottom) {
mClipRect.bottom = bottom;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index a00b497..41739c4 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -18,9 +18,13 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Outline;
import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.util.ArraySet;
@@ -28,7 +32,9 @@
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
+import android.view.ViewOutlineProvider;
import android.view.ViewPropertyAnimator;
+import android.view.ViewStub;
import android.view.WindowInsets;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
@@ -45,20 +51,24 @@
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
+import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
import com.android.systemui.recents.events.activity.HideHistoryEvent;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
import com.android.systemui.recents.events.activity.TaskStackUpdatedEvent;
+import com.android.systemui.recents.events.activity.ToggleHistoryEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
+import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
+import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
+import com.android.systemui.recents.history.RecentsHistoryView;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
@@ -80,6 +90,8 @@
public class RecentsView extends FrameLayout {
private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135;
+ private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
+ private static final float DEFAULT_SCRIM_ALPHA = 0.33f;
private final Handler mHandler;
@@ -88,11 +100,16 @@
private RecentsAppWidgetHostView mSearchBar;
private TextView mHistoryButton;
private View mEmptyView;
+ private RecentsHistoryView mHistoryView;
+
private boolean mAwaitingFirstLayout = true;
private boolean mLastTaskLaunchedWasFreeform;
private Rect mSystemInsets = new Rect();
private int mDividerSize;
+ private ColorDrawable mBackgroundScrim = new ColorDrawable(Color.BLACK);
+ private Animator mBackgroundScrimAnimator;
+
private RecentsTransitionHelper mTransitionHelper;
private RecentsViewTouchHandler mTouchHandler;
@@ -127,17 +144,28 @@
mTouchHandler = new RecentsViewTouchHandler(this);
mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
+ final float cornerRadius = context.getResources().getDimensionPixelSize(
+ R.dimen.recents_task_view_rounded_corners_radius);
LayoutInflater inflater = LayoutInflater.from(context);
mHistoryButton = (TextView) inflater.inflate(R.layout.recents_history_button, this, false);
mHistoryButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- EventBus.getDefault().send(new ShowHistoryEvent());
+ EventBus.getDefault().send(new ToggleHistoryEvent());
+ }
+ });
+ mHistoryButton.setClipToOutline(true);
+ mHistoryButton.setOutlineProvider(new ViewOutlineProvider() {
+ @Override
+ public void getOutline(View view, Outline outline) {
+ outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), cornerRadius);
}
});
addView(mHistoryButton);
mEmptyView = inflater.inflate(R.layout.recents_empty, this, false);
addView(mEmptyView);
+
+ setBackground(mBackgroundScrim);
}
/** Set/get the bsp root node */
@@ -162,6 +190,15 @@
addView(mTaskStackView);
}
+ // If we are already occluded by the app, then just set the default background scrim now.
+ // Otherwise, defer until the enter animation completes to animate the scrim with the
+ // tasks for the home animation.
+ if (launchState.launchedFromAppWithThumbnail || mStack.getTaskCount() == 0) {
+ mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
+ } else {
+ mBackgroundScrim.setAlpha(0);
+ }
+
// Update the top level view's visibilities
if (stack.getTaskCount() > 0) {
hideEmptyView();
@@ -181,6 +218,13 @@
}
/**
+ * Returns whether the history is visible or not.
+ */
+ public boolean isHistoryVisible() {
+ return mHistoryView != null && mHistoryView.isVisible();
+ }
+
+ /**
* Returns the currently set task stack.
*/
public TaskStack getTaskStack() {
@@ -304,13 +348,6 @@
mHistoryButton.bringToFront();
}
- /**
- * Returns the last known system insets.
- */
- public Rect getSystemInsets() {
- return mSystemInsets;
- }
-
@Override
protected void onAttachedToWindow() {
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
@@ -352,17 +389,23 @@
mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
}
- // Measure the empty view
- measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ // Measure the empty view to the full size of the screen
+ if (mEmptyView.getVisibility() != GONE) {
+ measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ }
- // Measure the history button with the full space above the stack, but width-constrained
- // to the stack
+ // Measure the history view
+ if (mHistoryView != null && mHistoryView.getVisibility() != GONE) {
+ measureChild(mHistoryView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+ }
+
+ // Measure the history button within the constraints of the space above the stack
Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
measureChild(mHistoryButton,
- MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(historyButtonRect.height(),
- MeasureSpec.EXACTLY));
+ MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(historyButtonRect.height(), MeasureSpec.AT_MOST));
setMeasuredDimension(width, height);
}
@@ -389,13 +432,24 @@
}
// Layout the empty view
- mEmptyView.layout(left, top, right, bottom);
+ if (mEmptyView.getVisibility() != GONE) {
+ mEmptyView.layout(left, top, right, bottom);
+ }
- // Layout the history button left-aligned with the stack, but offset from the top of the
- // view
+ // Layout the history view
+ if (mHistoryView != null && mHistoryView.getVisibility() != GONE) {
+ mHistoryView.layout(left, top, right, bottom);
+ }
+
+ // Layout the history button such that its drawable is left-aligned with the stack,
+ // vertically centered in the available space above the stack
Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
- mHistoryButton.layout(historyButtonRect.left, historyButtonRect.top,
- historyButtonRect.right, historyButtonRect.bottom);
+ int historyLeft = historyButtonRect.left - mHistoryButton.getPaddingStart();
+ int historyTop = historyButtonRect.top +
+ (historyButtonRect.height() - mHistoryButton.getMeasuredHeight()) / 2;
+ mHistoryButton.layout(historyLeft, historyTop,
+ historyLeft + mHistoryButton.getMeasuredWidth(),
+ historyTop + mHistoryButton.getMeasuredHeight());
if (mAwaitingFirstLayout) {
mAwaitingFirstLayout = false;
@@ -464,10 +518,8 @@
// Hide the history button
int taskViewExitToHomeDuration = getResources().getInteger(
R.integer.recents_task_exit_to_home_duration);
- hideHistoryButton(taskViewExitToHomeDuration);
-
- // If we are going home, cancel the previous task's window transition
- EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
+ hideHistoryButton(taskViewExitToHomeDuration, false /* translate */);
+ animateBackgroundScrim(0f, taskViewExitToHomeDuration);
}
public final void onBusEvent(DragStartEvent event) {
@@ -572,57 +624,127 @@
animator.start();
}
- public final void onBusEvent(ShowHistoryEvent event) {
- // Hide the history button when the history view is shown
- hideHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
- event.getAnimationTrigger());
- event.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- setAlpha(0f);
- }
- });
- }
-
- public final void onBusEvent(HideHistoryEvent event) {
- // Show the history button when the history view is hidden
- setAlpha(1f);
- showHistoryButton(getResources().getInteger(R.integer.recents_history_transition_duration),
- event.getAnimationTrigger());
- }
-
- public final void onBusEvent(ShowHistoryButtonEvent event) {
- showHistoryButton(150);
- }
-
- public final void onBusEvent(HideHistoryButtonEvent event) {
- hideHistoryButton(100);
- }
-
public final void onBusEvent(TaskStackUpdatedEvent event) {
mStack.setTasks(event.stack.computeAllTasksList(), true /* notifyStackChanges */);
mStack.createAffiliatedGroupings(getContext());
}
+ public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
+ RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+ if (!launchState.launchedFromAppWithThumbnail && mStack.getTaskCount() > 0) {
+ int taskViewEnterFromHomeDuration = getResources().getInteger(
+ R.integer.recents_task_enter_from_home_duration);
+ animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, taskViewEnterFromHomeDuration);
+ }
+ }
+
+ public final void onBusEvent(UpdateBackgroundScrimEvent event) {
+ animateBackgroundScrim(event.alpha, DEFAULT_UPDATE_SCRIM_DURATION);
+ }
+
+ public final void onBusEvent(ResetBackgroundScrimEvent event) {
+ animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
+ }
+
+ public final void onBusEvent(RecentsVisibilityChangedEvent event) {
+ if (!event.visible) {
+ // Reset the view state
+ mAwaitingFirstLayout = true;
+ mLastTaskLaunchedWasFreeform = false;
+ hideHistoryButton(0, false /* translate */);
+ }
+ }
+
+ public final void onBusEvent(ToggleHistoryEvent event) {
+ if (mHistoryView != null && mHistoryView.isVisible()) {
+ EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
+ } else {
+ EventBus.getDefault().send(new ShowHistoryEvent());
+ }
+ }
+
+ public final void onBusEvent(ShowHistoryEvent event) {
+ if (mHistoryView == null) {
+ mHistoryView = (RecentsHistoryView) LayoutInflater.from(getContext()).inflate(
+ R.layout.recents_history, this, false);
+ addView(mHistoryView);
+
+ // Since this history view is inflated by a view stub after the insets have already
+ // been applied, we have to set them ourselves initial from the insets that were last
+ // provided.
+ mHistoryView.setSystemInsets(mSystemInsets);
+ mHistoryView.setHeaderHeight(mHistoryButton.getMeasuredHeight());
+ mHistoryButton.bringToFront();
+ }
+
+ // Animate the empty view in parallel with the history view (the task view animations are
+ // handled in TaskStackView)
+ Rect stackRect = mTaskStackView.mLayoutAlgorithm.mStackRect;
+ if (mEmptyView.getVisibility() == View.VISIBLE) {
+ int historyTransitionDuration = getResources().getInteger(
+ R.integer.recents_history_transition_duration);
+ mEmptyView.animate()
+ .alpha(0f)
+ .translationY(stackRect.bottom)
+ .setDuration(historyTransitionDuration)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ mEmptyView.setVisibility(View.INVISIBLE);
+ }
+ })
+ .start();
+ }
+
+ mHistoryView.show(mStack, stackRect.height());
+ }
+
+ public final void onBusEvent(HideHistoryEvent event) {
+ // Animate the empty view in parallel with the history view (the task view animations are
+ // handled in TaskStackView)
+ Rect stackRect = mTaskStackView.mLayoutAlgorithm.mStackRect;
+ if (mStack.getTaskCount() == 0) {
+ int historyTransitionDuration = getResources().getInteger(
+ R.integer.recents_history_transition_duration);
+ mEmptyView.setVisibility(View.VISIBLE);
+ mEmptyView.animate()
+ .alpha(1f)
+ .translationY(0)
+ .setDuration(historyTransitionDuration)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .start();
+ }
+
+ mHistoryView.hide(event.animate, stackRect.height());
+ }
+
+ public final void onBusEvent(ShowHistoryButtonEvent event) {
+ showHistoryButton(150, event.translate);
+ }
+
+ public final void onBusEvent(HideHistoryButtonEvent event) {
+ hideHistoryButton(100, true /* translate */);
+ }
+
/**
* Shows the history button.
*/
- private void showHistoryButton(final int duration) {
- ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
- showHistoryButton(duration, postAnimationTrigger);
- postAnimationTrigger.flushLastDecrementRunnables();
- }
-
- private void showHistoryButton(final int duration,
- final ReferenceCountedTrigger postHideHistoryAnimationTrigger) {
- mHistoryButton.setText(getContext().getString(R.string.recents_history_label_format,
- mStack.getHistoricalTasks().size()));
+ private void showHistoryButton(final int duration, final boolean translate) {
+ final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
if (mHistoryButton.getVisibility() == View.INVISIBLE) {
mHistoryButton.setVisibility(View.VISIBLE);
mHistoryButton.setAlpha(0f);
- postHideHistoryAnimationTrigger.addLastDecrementRunnable(new Runnable() {
+ if (translate) {
+ mHistoryButton.setTranslationY(-mHistoryButton.getMeasuredHeight() * 0.25f);
+ }
+ postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
@Override
public void run() {
+ if (translate) {
+ mHistoryButton.animate()
+ .translationY(0f);
+ }
mHistoryButton.animate()
.alpha(1f)
.setDuration(duration)
@@ -632,34 +754,42 @@
}
});
}
+ postAnimationTrigger.flushLastDecrementRunnables();
}
/**
* Hides the history button.
*/
- private void hideHistoryButton(int duration) {
- ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
- hideHistoryButton(duration, postAnimationTrigger);
+ private void hideHistoryButton(int duration, boolean translate) {
+ final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
+ hideHistoryButton(duration, translate, postAnimationTrigger);
postAnimationTrigger.flushLastDecrementRunnables();
}
- private void hideHistoryButton(int duration,
- final ReferenceCountedTrigger postHideStackAnimationTrigger) {
+ /**
+ * Hides the history button.
+ */
+ private void hideHistoryButton(int duration, boolean translate,
+ final ReferenceCountedTrigger postAnimationTrigger) {
if (mHistoryButton.getVisibility() == View.VISIBLE) {
+ if (translate) {
+ mHistoryButton.animate()
+ .translationY(-mHistoryButton.getMeasuredHeight() * 0.25f);
+ }
mHistoryButton.animate()
.alpha(0f)
.setDuration(duration)
- .setInterpolator(mFastOutLinearInInterpolator)
+ .setInterpolator(mFastOutSlowInInterpolator)
.withEndAction(new Runnable() {
@Override
public void run() {
mHistoryButton.setVisibility(View.INVISIBLE);
- postHideStackAnimationTrigger.decrement();
+ postAnimationTrigger.decrement();
}
})
.withLayer()
.start();
- postHideStackAnimationTrigger.increment();
+ postAnimationTrigger.increment();
}
}
@@ -696,11 +826,18 @@
}
}
- public final void onBusEvent(RecentsVisibilityChangedEvent event) {
- if (!event.visible) {
- // Reset the view state
- mAwaitingFirstLayout = true;
- mLastTaskLaunchedWasFreeform = false;
- }
+ /**
+ * Animates the background scrim to the given {@param alpha}.
+ */
+ private void animateBackgroundScrim(float alpha, int duration) {
+ Utilities.cancelAnimationWithoutCallbacks(mBackgroundScrimAnimator);
+ int alphaInt = (int) (alpha * 255);
+ mBackgroundScrimAnimator = ObjectAnimator.ofInt(mBackgroundScrim, Utilities.DRAWABLE_ALPHA,
+ mBackgroundScrim.getAlpha(), alphaInt);
+ mBackgroundScrimAnimator.setDuration(duration);
+ mBackgroundScrimAnimator.setInterpolator(alphaInt > mBackgroundScrim.getAlpha()
+ ? PhoneStatusBar.ALPHA_OUT
+ : PhoneStatusBar.ALPHA_IN);
+ mBackgroundScrimAnimator.start();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 9618f212d..2254dfc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -30,12 +30,9 @@
Context mContext;
- View mStatusBarScrimView;
View mNavBarScrimView;
boolean mHasNavBarScrim;
- boolean mShouldAnimateStatusBarScrim;
- boolean mHasStatusBarScrim;
boolean mShouldAnimateNavBarScrim;
int mNavBarScrimEnterDuration;
@@ -45,7 +42,6 @@
public SystemBarScrimViews(Activity activity) {
mContext = activity;
- mStatusBarScrimView = activity.findViewById(R.id.status_bar_scrim);
mNavBarScrimView = activity.findViewById(R.id.nav_bar_scrim);
mNavBarScrimEnterDuration = activity.getResources().getInteger(
R.integer.recents_nav_bar_scrim_enter_duration);
@@ -59,17 +55,12 @@
* Prepares the scrim views for animating when entering Recents. This will be called before
* the first draw.
*/
- public void prepareEnterRecentsAnimation(boolean hasStatusBarScrim, boolean animateStatusBarScrim,
- boolean hasNavBarScrim, boolean animateNavBarScrim) {
- mHasNavBarScrim = hasStatusBarScrim;
- mShouldAnimateStatusBarScrim = animateStatusBarScrim;
- mHasStatusBarScrim = hasNavBarScrim;
+ public void prepareEnterRecentsAnimation(boolean hasNavBarScrim, boolean animateNavBarScrim) {
+ mHasNavBarScrim = hasNavBarScrim;
mShouldAnimateNavBarScrim = animateNavBarScrim;
mNavBarScrimView.setVisibility(mHasNavBarScrim && !mShouldAnimateNavBarScrim ?
View.VISIBLE : View.INVISIBLE);
- mStatusBarScrimView.setVisibility(mHasStatusBarScrim && !mShouldAnimateStatusBarScrim ?
- View.VISIBLE : View.INVISIBLE);
}
/**** EventBus events ****/
@@ -78,20 +69,6 @@
* Starts animating the scrim views when entering Recents.
*/
public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
- if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
- mStatusBarScrimView.setTranslationY(-mStatusBarScrimView.getMeasuredHeight());
- mStatusBarScrimView.animate()
- .translationY(0)
- .setDuration(mNavBarScrimEnterDuration)
- .setInterpolator(mQuintOutInterpolator)
- .withStartAction(new Runnable() {
- @Override
- public void run() {
- mStatusBarScrimView.setVisibility(View.VISIBLE);
- }
- })
- .start();
- }
if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
mNavBarScrimView.animate()
@@ -115,14 +92,6 @@
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
int taskViewExitToAppDuration = mContext.getResources().getInteger(
R.integer.recents_task_exit_to_app_duration);
- if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
- mStatusBarScrimView.animate()
- .translationY(-mStatusBarScrimView.getMeasuredHeight())
- .setStartDelay(0)
- .setDuration(taskViewExitToAppDuration)
- .setInterpolator(mFastOutSlowInInterpolator)
- .start();
- }
if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
mNavBarScrimView.animate()
.translationY(mNavBarScrimView.getMeasuredHeight())
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index ccbb329..d550d83 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -138,7 +138,7 @@
} else if (launchState.launchedFromHome) {
// Move the task view off screen (below) so we can animate it in
RectF bounds = new RectF(mTmpTransform.rect);
- bounds.offset(0, offscreenY);
+ bounds.offsetTo(bounds.left, offscreenY);
tv.setLeftTopRightBottom((int) bounds.left, (int) bounds.top, (int) bounds.right,
(int) bounds.bottom);
}
@@ -259,7 +259,7 @@
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
null);
- mTmpTransform.rect.offset(0, offscreenY);
+ mTmpTransform.rect.offsetTo(mTmpTransform.rect.left, offscreenY);
mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
}
}
@@ -346,61 +346,58 @@
}
/**
- * Starts the animation to hide the {@link TaskView}s when the history is shown. The history
- * view's animation will be deferred until all the {@link TaskView}s are finished animating.
+ * Starts the animation to hide the {@link TaskView}s when the history is shown.
*/
public void startShowHistoryAnimation(ReferenceCountedTrigger postAnimationTrigger) {
Resources res = mStackView.getResources();
TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
TaskStackViewScroller stackScroller = mStackView.getScroller();
+ int offscreenY = stackLayout.mStackRect.bottom;
int historyTransitionDuration = res.getInteger(
R.integer.recents_history_transition_duration);
+ int startDelayIncr = 16;
List<TaskView> taskViews = mStackView.getTaskViews();
int taskViewCount = taskViews.size();
for (int i = taskViewCount - 1; i >= 0; i--) {
TaskView tv = taskViews.get(i);
Task task = tv.getTask();
- TaskViewAnimation taskAnimation = new TaskViewAnimation(
- historyTransitionDuration, PhoneStatusBar.ALPHA_OUT,
+ TaskViewAnimation taskAnimation = new TaskViewAnimation(startDelayIncr * i,
+ historyTransitionDuration, mFastOutSlowInInterpolator,
postAnimationTrigger.decrementOnAnimationEnd());
postAnimationTrigger.increment();
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
null);
mTmpTransform.alpha = 0f;
+ mTmpTransform.rect.offsetTo(mTmpTransform.rect.left, offscreenY);
mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
}
}
/**
- * Starts the animation to show the {@link TaskView}s when the history is hidden. The
- * {@link TaskView} animations will be deferred until the history view has been animated away.
+ * Starts the animation to show the {@link TaskView}s when the history is hidden.
*/
- public void startHideHistoryAnimation(final ReferenceCountedTrigger postAnimationTrigger) {
- final Resources res = mStackView.getResources();
- final TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
- final TaskStackViewScroller stackScroller = mStackView.getScroller();
+ public void startHideHistoryAnimation() {
+ Resources res = mStackView.getResources();
+ TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
+ TaskStackViewScroller stackScroller = mStackView.getScroller();
- final int historyTransitionDuration = res.getInteger(
+ int historyTransitionDuration = res.getInteger(
R.integer.recents_history_transition_duration);
+ int startDelayIncr = 16;
List<TaskView> taskViews = mStackView.getTaskViews();
int taskViewCount = taskViews.size();
for (int i = taskViewCount - 1; i >= 0; i--) {
- final TaskView tv = taskViews.get(i);
- postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- TaskViewAnimation taskAnimation = new TaskViewAnimation(
- historyTransitionDuration, PhoneStatusBar.ALPHA_IN);
- stackLayout.getStackTransform(tv.getTask(), stackScroller.getStackScroll(),
- mTmpTransform, null);
- mTmpTransform.alpha = 1f;
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
- }
- });
+ TaskView tv = taskViews.get(i);
+ TaskViewAnimation taskAnimation = new TaskViewAnimation(startDelayIncr * i,
+ historyTransitionDuration, mFastOutSlowInInterpolator);
+ stackLayout.getStackTransform(tv.getTask(), stackScroller.getStackScroll(),
+ mTmpTransform, null);
+ mTmpTransform.alpha = 1f;
+ mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 93849dc..bb37c04 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -354,6 +354,7 @@
mStackBottomOffset = mSystemInsets.bottom + heightPadding;
state.computeRects(mFreeformRect, mStackRect, taskStackBounds, widthPadding, heightPadding,
mStackBottomOffset);
+ // The history button will take the full un-padded header space above the stack
mHistoryButtonRect.set(mStackRect.left, mStackRect.top - heightPadding,
mStackRect.right, mStackRect.top + mFocusedPeekHeight);
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 7423b78..1c545c8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -64,6 +64,7 @@
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
import com.android.systemui.recents.events.ui.StackViewScrolledEvent;
import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
+import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
@@ -74,11 +75,13 @@
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
import com.android.systemui.recents.misc.DozeTrigger;
+import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import java.lang.ref.Reference;
import java.util.ArrayList;
import java.util.List;
@@ -1117,12 +1120,19 @@
// We can get spurious measure passes with the old bounds when docking, and since we are
// using the current stack bounds during drag and drop, don't overwrite them until we
// actually get new bounds
+ boolean requiresLayout = false;
if (!taskStackBounds.equals(mStableStackBounds)) {
mStableStackBounds.set(taskStackBounds);
mStackBounds.set(taskStackBounds);
+ requiresLayout = true;
}
- mLayoutAlgorithm.setSystemInsets(systemInsets);
- requestLayout();
+ if (!systemInsets.equals(mLayoutAlgorithm.mSystemInsets)) {
+ mLayoutAlgorithm.setSystemInsets(systemInsets);
+ requiresLayout = true;
+ }
+ if (requiresLayout) {
+ requestLayout();
+ }
}
/**
@@ -1235,7 +1245,7 @@
// Update the history button visibility
if (shouldShowHistoryButton() &&
mStackScroller.getStackScroll() < SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new ShowHistoryButtonEvent());
+ EventBus.getDefault().send(new ShowHistoryButtonEvent(false /* translate */));
} else {
EventBus.getDefault().send(new HideHistoryButtonEvent());
}
@@ -1468,13 +1478,15 @@
relayoutTaskViewsOnNextFrame(animation);
}
- if (shouldShowHistoryButton() &&
- prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
- curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new ShowHistoryButtonEvent());
- } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
- curScroll >= HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new HideHistoryButtonEvent());
+ if (mEnterAnimationComplete) {
+ if (shouldShowHistoryButton() &&
+ prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
+ curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new ShowHistoryButtonEvent(true /* translate */));
+ } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
+ curScroll >= HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new HideHistoryButtonEvent());
+ }
}
}
@@ -1753,11 +1765,19 @@
}
public final void onBusEvent(ShowHistoryEvent event) {
- mAnimationHelper.startShowHistoryAnimation(event.getAnimationTrigger());
+ ReferenceCountedTrigger postAnimTrigger = new ReferenceCountedTrigger();
+ postAnimTrigger.addLastDecrementRunnable(new Runnable() {
+ @Override
+ public void run() {
+ setVisibility(View.INVISIBLE);
+ }
+ });
+ mAnimationHelper.startShowHistoryAnimation(postAnimTrigger);
}
public final void onBusEvent(HideHistoryEvent event) {
- mAnimationHelper.startHideHistoryAnimation(event.getAnimationTrigger());
+ setVisibility(View.VISIBLE);
+ mAnimationHelper.startHideHistoryAnimation();
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
index 363ad66..74b16d0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAnimation.java
@@ -45,6 +45,10 @@
this(0 /* startDelay */, duration, interpolator, listener);
}
+ public TaskViewAnimation(int startDelay, int duration, Interpolator interpolator) {
+ this(startDelay, duration, interpolator, null);
+ }
+
public TaskViewAnimation(int startDelay, int duration, Interpolator interpolator,
Animator.AnimatorListener listener) {
this.startDelay = startDelay;