Fixing issues with dim not animating, adding dismiss button delay, tweaking empty recents text. (Bug 15431590, 15573497)
Change-Id: I9c11e04cd52f9e000d8ba3e443f2500c9aa7edbb
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index ac6450b..c0ddde1 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -21,7 +21,6 @@
android:gravity="center"
android:textSize="20sp"
android:textColor="#ffffffff"
- android:textStyle="italic"
android:text="@string/recents_empty_message"
android:fontFamily="sans-serif-light"
android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 85d2f16..23f2796 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -56,6 +56,7 @@
android:layout_marginEnd="4dp"
android:layout_gravity="center_vertical|end"
android:padding="18dp"
+ android:visibility="invisible"
android:src="@drawable/recents_dismiss_light" />
</com.android.systemui.recents.views.TaskBarView>
</com.android.systemui.recents.views.TaskView>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index b39fa84..09a94f5 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -108,6 +108,8 @@
<!-- milliseconds before the heads up notification accepts touches. -->
<integer name="heads_up_sensitivity_delay">700</integer>
+ <!-- The duration in seconds to wait before the dismiss buttons are shown. -->
+ <integer name="recents_task_bar_dismiss_delay_seconds">3</integer>
<!-- The min animation duration for animating views that are currently visible. -->
<integer name="recents_filter_animate_current_views_min_duration">175</integer>
<!-- The min animation duration for animating views that are newly visible. -->
diff --git a/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java
new file mode 100644
index 0000000..247aa6f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/DozeTrigger.java
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents;
+
+import android.os.Handler;
+
+/**
+ * A dozer is a class that fires a trigger after it falls asleep. You can occasionally poke it to
+ * wake it up, but it will fall asleep if left untouched.
+ */
+public class DozeTrigger {
+
+ Handler mHandler;
+
+ boolean mIsDozing;
+ boolean mHasTriggered;
+ int mDozeDurationSeconds;
+ Runnable mSleepRunnable;
+
+ // Sleep-runnable
+ Runnable mDozeRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mSleepRunnable.run();
+ mIsDozing = false;
+ mHasTriggered = true;
+ }
+ };
+
+ public DozeTrigger(int dozeDurationSeconds, Runnable sleepRunnable) {
+ mHandler = new Handler();
+ mDozeDurationSeconds = dozeDurationSeconds;
+ mSleepRunnable = sleepRunnable;
+ }
+
+ /** Starts dozing. This also resets the trigger flag. */
+ public void startDozing() {
+ poke();
+ mHasTriggered = false;
+ }
+
+ /** Poke this dozer to wake it up for a little bit. */
+ public void poke() {
+ mHandler.removeCallbacks(mDozeRunnable);
+ mHandler.postDelayed(mDozeRunnable, mDozeDurationSeconds * 1000);
+ mIsDozing = true;
+ }
+
+ /** Returns whether we are dozing or not. */
+ public boolean isDozing() {
+ return mIsDozing;
+ }
+
+ /** Returns whether the trigger has fired at least once. */
+ public boolean hasTriggered() {
+ return mHasTriggered;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index f9c219b..05c3252 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -527,6 +527,11 @@
}
@Override
+ public void onUserInteraction() {
+ mRecentsView.onUserInteraction();
+ }
+
+ @Override
public void onBackPressed() {
// If we are mid-animation into Recents, then reverse it and finish
if (mFullScreenshotView == null ||
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index a0c5253..b1f3733 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -89,6 +89,7 @@
public int taskBarEnterAnimDuration;
public int taskBarEnterAnimDelay;
public int taskBarExitAnimDuration;
+ public int taskBarDismissDozeDelaySeconds;
/** Nav bar scrim */
public int navBarScrimEnterDuration;
@@ -205,6 +206,8 @@
res.getInteger(R.integer.recents_animate_task_bar_enter_delay);
taskBarExitAnimDuration =
res.getInteger(R.integer.recents_animate_task_bar_exit_duration);
+ taskBarDismissDozeDelaySeconds =
+ res.getInteger(R.integer.recents_task_bar_dismiss_delay_seconds);
// Nav bar scrim
navBarScrimEnterDuration =
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 a2c250c..d019037 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -307,6 +307,20 @@
}
}
+ /** Notifies each task view of the user interaction. */
+ public void onUserInteraction() {
+ // Get the first stack view
+ TaskStackView stackView = null;
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child instanceof TaskStackView) {
+ stackView = (TaskStackView) child;
+ stackView.onUserInteraction();
+ }
+ }
+ }
+
/** Focuses the next task in the first stack view */
public void focusNextTask(boolean forward) {
// Get the first stack view
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index 2c637a8..aae345b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -105,7 +105,7 @@
/** Synchronizes this bar view's properties with the task's transform */
void updateViewPropertiesToTaskTransform(TaskViewTransform animateFromTransform,
TaskViewTransform toTransform, int duration) {
- if (duration > 0) {
+ if (duration > 0 && (mDismissButton.getVisibility() == View.VISIBLE)) {
if (animateFromTransform != null) {
mDismissButton.setAlpha(animateFromTransform.dismissAlpha);
}
@@ -169,7 +169,7 @@
setTranslationY(-getMeasuredHeight());
animate()
.translationY(0)
- .setStartDelay(delay > -1 ? delay : mConfig.taskBarEnterAnimDelay)
+ .setStartDelay(delay)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(mConfig.taskBarEnterAnimDuration)
.withLayer()
@@ -178,6 +178,7 @@
/** Animates this task bar as it exits recents */
public void animateOnLaunchingTask(final Runnable r) {
+ // Animate the task bar out of the first task view
animate()
.translationY(-getMeasuredHeight())
.setStartDelay(0)
@@ -193,6 +194,28 @@
.start();
}
+ /** Animates this task bar if the user does not interact with the stack after a certain time. */
+ public void animateOnNoUserInteraction() {
+ mDismissButton.setVisibility(View.VISIBLE);
+ mDismissButton.setAlpha(0f);
+ mDismissButton.animate()
+ .alpha(1f)
+ .setStartDelay(0)
+ .setInterpolator(mConfig.fastOutLinearInInterpolator)
+ .setDuration(mConfig.taskBarEnterAnimDuration)
+ .withLayer()
+ .start();
+ }
+
+ /** Mark this task view that the user does has not interacted with the stack after a certain time. */
+ public void setOnNoUserInteraction() {
+ if (mDismissButton.getVisibility() != View.VISIBLE) {
+ mDismissButton.animate().cancel();
+ mDismissButton.setVisibility(View.VISIBLE);
+ mDismissButton.setAlpha(1f);
+ }
+ }
+
/** Enable the hw layers on this task view */
void enableHwLayers() {
mDismissButton.setLayerType(View.LAYER_TYPE_HARDWARE, null);
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 186565b..b503c36 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -38,6 +38,7 @@
import com.android.systemui.R;
import com.android.systemui.recents.Console;
import com.android.systemui.recents.Constants;
+import com.android.systemui.recents.DozeTrigger;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsPackageMonitor;
import com.android.systemui.recents.RecentsTaskLoader;
@@ -70,6 +71,7 @@
TaskStackViewCallbacks mCb;
ViewPool<TaskView, Task> mViewPool;
ArrayList<TaskViewTransform> mTaskTransforms = new ArrayList<TaskViewTransform>();
+ DozeTrigger mDozeTrigger;
// The various rects that define the stack view
Rect mRect = new Rect();
@@ -107,6 +109,17 @@
mTouchHandler = new TaskStackViewTouchHandler(context, this);
mViewPool = new ViewPool<TaskView, Task>(context, this);
mInflater = LayoutInflater.from(context);
+ mDozeTrigger = new DozeTrigger(mConfig.taskBarDismissDozeDelaySeconds, new Runnable() {
+ @Override
+ public void run() {
+ // Show the task bar dismiss buttons
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ TaskView tv = (TaskView) getChildAt(i);
+ tv.animateOnNoUserInteraction();
+ }
+ }
+ });
mHwLayersTrigger = new ReferenceCountedTrigger(getContext(), new Runnable() {
@Override
public void run() {
@@ -797,6 +810,9 @@
// Mark that we have completely the first layout
mAwaitingFirstLayout = false;
+ // Start dozing
+ mDozeTrigger.startDozing();
+
// Prepare the first view for its enter animation
int offsetTopAlign = -mTaskRect.top;
int offscreenY = mRect.bottom - (mTaskRect.top - mRect.top);
@@ -867,6 +883,15 @@
return isTransformedTouchPointInView(x, y, child, null);
}
+ /** Pokes the dozer on user interaction. */
+ void onUserInteraction() {
+ // If the dozer is not running, then either we have not yet laid out, or it has already
+ // fallen asleep, so just let it rest.
+ if (mDozeTrigger.isDozing()) {
+ mDozeTrigger.poke();
+ }
+ }
+
/**** TaskStackCallbacks Implementation ****/
@Override
@@ -1152,6 +1177,11 @@
// but just in case, re-enable it here
tv.setClipViewInStack(true);
+ // If the doze trigger has already fired, then update the state for this task view
+ if (mDozeTrigger.hasTriggered()) {
+ tv.setOnNoUserInteraction();
+ }
+
// Add/attach the view to the hierarchy
if (Console.Enabled) {
Console.log(Constants.Log.ViewPool.PoolCallbacks, " [TaskStackView|insertIndex]",
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 9e4386f..7376255 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,6 +16,7 @@
package com.android.systemui.recents.views;
+import android.animation.ObjectAnimator;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
@@ -93,6 +94,7 @@
super(context, attrs, defStyleAttr, defStyleRes);
mConfig = RecentsConfiguration.getInstance();
setWillNotDraw(false);
+ setDim(getDim());
}
@Override
@@ -206,7 +208,7 @@
setScaleX(1f);
setScaleY(1f);
setAlpha(1f);
- mDim = 0;
+ setDim(0);
invalidate();
}
@@ -251,6 +253,8 @@
if (isTaskViewFrontMost) {
// Hide the front most task bar view so we can animate it in
mBarView.prepareAnimateEnterRecents();
+ // Set the dim to 0 so we can animate it in
+ setDim(0);
}
} else if (mConfig.launchedFromHome) {
@@ -292,7 +296,13 @@
} else if (mConfig.launchedFromAppWithThumbnail) {
if (ctx.isFrontMost) {
// Animate the task bar of the first task view
- mBarView.animateOnEnterRecents(-1);
+ mBarView.animateOnEnterRecents(mConfig.taskBarEnterAnimDelay);
+ // Animate the dim into view as well
+ ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", getDimOverlayFromScale());
+ anim.setStartDelay(mConfig.taskBarEnterAnimDelay);
+ anim.setDuration(mConfig.taskBarEnterAnimDuration);
+ anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
+ anim.start();
}
} else if (mConfig.launchedFromHome) {
@@ -325,9 +335,27 @@
ctx.postAnimationTrigger.increment();
}
+ /** Animates this task view if the user does not interact with the stack after a certain time. */
+ public void animateOnNoUserInteraction() {
+ mBarView.animateOnNoUserInteraction();
+ }
+
+ /** Mark this task view that the user does has not interacted with the stack after a certain time. */
+ public void setOnNoUserInteraction() {
+ mBarView.setOnNoUserInteraction();
+ }
+
/** Animates this task view as it exits recents */
public void animateOnLaunchingTask(final Runnable r) {
mBarView.animateOnLaunchingTask(r);
+
+ // Animate the dim
+ if (mDim > 0) {
+ ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
+ anim.setDuration(mConfig.taskBarExitAnimDuration);
+ anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
+ anim.start();
+ }
}
/** Animates the deletion of this task view */
@@ -398,13 +426,29 @@
}
}
- /** Update the dim as a function of the scale of this view. */
- void updateDimOverlayFromScale() {
+ /** Returns the current dim. */
+ public void setDim(int dim) {
+ mDim = dim;
+ postInvalidateOnAnimation();
+ }
+
+ /** Returns the current dim. */
+ public int getDim() {
+ return mDim;
+ }
+
+ /** Compute the dim as a function of the scale of this view. */
+ int getDimOverlayFromScale() {
float minScale = Constants.Values.TaskStackView.StackPeekMinScale;
float scaleRange = 1f - minScale;
float dim = (1f - getScaleX()) / scaleRange;
dim = mDimInterpolator.getInterpolation(Math.min(dim, 1f));
- mDim = Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
+ return Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
+ }
+
+ /** Update the dim as a function of the scale of this view. */
+ void updateDimOverlayFromScale() {
+ setDim(getDimOverlayFromScale());
}
@Override