Modified focus state
Change-Id: If5e5723ea3b16e7e9805eba9208a85557565b360
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 47e24e8..2b8ca89 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -10,6 +10,16 @@
public void setGlowScale(float);
}
+-keep class com.android.systemui.recents.views.TaskView {
+ public void setHighlightProgress(float);
+ public float getHighlightProgress();
+}
+
+-keep class com.android.systemui.recents.views.TaskViewHeader {
+ public void setFocusProgress(float);
+ public float getFocusProgress();
+}
+
-keep class com.android.systemui.statusbar.phone.PhoneStatusBar
-keep class com.android.systemui.statusbar.tv.TvStatusBar
-keep class com.android.systemui.recents.*
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 0dcbe88..3438502 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -26,6 +26,7 @@
<color name="notification_panel_solid_background">#ff000000</color>
<drawable name="status_bar_recents_app_thumbnail_background">#88000000</drawable>
<color name="status_bar_recents_app_label_color">#ffffffff</color>
+ <color name="status_bar_recents_highlight_color">#ff009688</color>
<drawable name="status_bar_notification_row_background_color">#ff090909</drawable>
<color name="notification_list_shadow_top">#80000000</color>
<drawable name="recents_callout_line">#99ffffff</drawable>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 5d06768..e00b1f4 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -167,7 +167,7 @@
<integer name="recents_enter_from_app_transition_duration">325</integer>
<!-- The duration for animating the task decorations in after transitioning from an app. -->
- <integer name="recents_task_enter_from_app_duration">200</integer>
+ <integer name="recents_task_enter_from_app_duration">350</integer>
<!-- The duration for animating the task decorations out before transitioning to an app. -->
<integer name="recents_task_exit_to_app_duration">125</integer>
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 3c7d48c..4214558 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -409,7 +409,7 @@
// Get the first stack view
List<TaskStackView> stackViews = getTaskStackViews();
if (!stackViews.isEmpty()) {
- stackViews.get(0).focusNextTask(forward, true);
+ stackViews.get(0).focusNextTask(forward);
}
}
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 a8a18fc..571a9ef 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -218,6 +218,8 @@
mUIDozeTrigger.resetTrigger();
}
mStackScroller.reset();
+
+ mStartEnterAnimationCompleted = false;
}
/** Requests that the views be synchronized with the model */
@@ -500,26 +502,34 @@
}
/** Focuses the task at the specified index in the stack */
- void focusTask(int taskIndex, boolean scrollToNewPosition, final boolean animateFocusedState) {
+ void focusTask(int taskIndex, boolean scrollToNewPosition) {
// Return early if the task is already focused
if (taskIndex == mFocusedTaskIndex) return;
if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
+ resetFocusedTask();
mFocusedTaskIndex = taskIndex;
mPrevAccessibilityFocusedIndex = taskIndex;
// Focus the view if possible, otherwise, focus the view after we scroll into position
+ Runnable postScrollRunnable = null;
final Task t = mStack.getTasks().get(mFocusedTaskIndex);
- Runnable postScrollRunnable = new Runnable() {
- @Override
- public void run() {
- TaskView tv = getChildViewForTask(t);
- if (tv != null) {
- tv.setFocusedTask(animateFocusedState);
- tv.requestAccessibilityFocus();
+ final TaskView tv = getChildViewForTask(t);
+ if (tv != null) {
+ tv.setFocusedTask();
+ tv.requestAccessibilityFocus();
+ } else {
+ postScrollRunnable = new Runnable() {
+ @Override
+ public void run() {
+ TaskView tv = getChildViewForTask(t);
+ if (tv != null) {
+ tv.setFocusedTask();
+ tv.requestAccessibilityFocus();
+ }
}
- }
- };
+ };
+ }
// Scroll the view into position (just center it in the curve)
if (scrollToNewPosition) {
@@ -574,7 +584,7 @@
* the change in focus, as well as whether to scroll to fit the
* task into view.
*/
- public void focusNextTask(boolean forward, boolean animateFocusedState) {
+ public void focusNextTask(boolean forward) {
// Find the next index to focus
int numTasks = mStack.getTaskCount();
if (numTasks == 0) return;
@@ -587,7 +597,7 @@
newIndex = 0;
}
- focusTask(newIndex, true, animateFocusedState);
+ focusTask(newIndex, true);
}
/** Dismisses the focused task. */
@@ -663,14 +673,14 @@
switch (action) {
case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
if (mPrevAccessibilityFocusedIndex > 0) {
- focusNextTask(true, false);
+ focusNextTask(true);
return true;
}
}
break;
case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
if (mPrevAccessibilityFocusedIndex < mStack.getTaskCount() - 1) {
- focusNextTask(false, false);
+ focusNextTask(false);
return true;
}
}
@@ -869,11 +879,9 @@
// enter animation).
if (mConfig.launchedWithAltTab) {
if (mConfig.launchedFromAppWithThumbnail) {
- focusTask(Math.max(0, mStack.getTaskCount() - 2), false,
- mConfig.launchedHasConfigurationChanged);
+ focusTask(Math.max(0, mStack.getTaskCount() - 2), false);
} else {
- focusTask(Math.max(0, mStack.getTaskCount() - 1), false,
- mConfig.launchedHasConfigurationChanged);
+ focusTask(Math.max(0, mStack.getTaskCount() - 1), false);
}
}
@@ -948,7 +956,7 @@
0 <= mFocusedTaskIndex && mFocusedTaskIndex < tasks.size()) {
TaskView tv = getChildViewForTask(tasks.get(mFocusedTaskIndex));
if (tv != null) {
- tv.setFocusedTask(true);
+ tv.setFocusedTask();
}
}
@@ -1404,7 +1412,7 @@
if (nextTv != null) {
// Focus the next task, and only animate the visible state if we are launched
// from Alt-Tab
- nextTv.setFocusedTask(mConfig.launchedWithAltTab);
+ nextTv.setFocusedTask();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index be618e2..25fb71e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -420,11 +420,11 @@
float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
if (vScroll > 0) {
if (mSv.ensureFocusedTask(true)) {
- mSv.focusNextTask(true, false);
+ mSv.focusNextTask(true);
}
} else {
if (mSv.ensureFocusedTask(true)) {
- mSv.focusNextTask(false, false);
+ mSv.focusNextTask(false);
}
}
return true;
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 5ad8e69..55aba75 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
@@ -26,6 +26,9 @@
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
@@ -48,7 +51,6 @@
public void onTaskViewDismissed(TaskView tv);
public void onTaskViewClipStateChanged(TaskView tv);
public void onTaskViewFocusChanged(TaskView tv, boolean focused);
-
public void onTaskResize(TaskView tv);
}
@@ -76,6 +78,22 @@
View mActionButtonView;
TaskViewCallbacks mCb;
+ // Focus animation
+ float mHighlightProgress;
+ Paint mHighlightPaint = new Paint();
+ int mHighlightColor = 0xff009688;
+ int mHighlightAlpha = 0x50;
+ static Interpolator sHighlightInInterpolator = new OvershootInterpolator(2);
+ static Interpolator sHighlightInRadiusInterpolator = new DecelerateInterpolator();
+ static Interpolator sHighlightOutInterpolator = new DecelerateInterpolator();
+ ObjectAnimator mHighlightAnimator;
+ static long sHighlightInDurationMs = 350;
+ static long sHighlightOutDurationMs = 200;
+ float mHighlightInCircleRadiusProgress;
+ int mHighlightInFillAlpha;
+ int mHighlightInCircleAlpha;
+ int mHighlightOutFillAlpha;
+
// Optimizations
ValueAnimator.AnimatorUpdateListener mUpdateDimListener =
new ValueAnimator.AnimatorUpdateListener() {
@@ -85,7 +103,6 @@
}
};
-
public TaskView(Context context) {
this(context, null);
}
@@ -110,6 +127,11 @@
setBackground(new FakeShadowDrawable(context.getResources(), mConfig));
}
setOutlineProvider(mViewBounds);
+
+ mHighlightAnimator = ObjectAnimator.ofFloat(this, "highlightProgress", 1f);
+ mHighlightColor =
+ context.getResources().getColor(R.color.status_bar_recents_highlight_color);
+ mHighlightPaint.setColor(mHighlightColor);
}
/** Set callback */
@@ -185,7 +207,7 @@
}
void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration,
- ValueAnimator.AnimatorUpdateListener updateCallback) {
+ ValueAnimator.AnimatorUpdateListener updateCallback) {
// Apply the transform
toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator, false,
!mConfig.fakeShadows, updateCallback);
@@ -235,10 +257,12 @@
fromTransform.alpha = 0f;
}
- /** Prepares this task view for the enter-recents animations. This is called earlier in the
- * first layout because the actual animation into recents may take a long time. */
+ /**
+ * Prepares this task view for the enter-recents animations. This is called earlier in the
+ * first layout because the actual animation into recents may take a long time.
+ */
void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask,
- boolean occludesLaunchTarget, int offscreenY) {
+ boolean occludesLaunchTarget, int offscreenY) {
int initialDim = getDim();
if (mConfig.launchedHasConfigurationChanged) {
// Just load the views as-is
@@ -299,7 +323,8 @@
} else {
// Animate the task up if it was occluding the launch target
if (ctx.currentTaskOccludesLaunchTarget) {
- setTranslationY(transform.translationY + mConfig.taskViewAffiliateGroupEnterOffsetPx);
+ setTranslationY(transform.translationY
+ + mConfig.taskViewAffiliateGroupEnterOffsetPx);
setAlpha(0f);
animate().alpha(1f)
.translationY(transform.translationY)
@@ -424,13 +449,15 @@
// If this is another view in the task grouping and is in front of the launch task,
// animate it away first
if (occludesLaunchTarget) {
- animate().alpha(0f)
- .translationY(getTranslationY() + mConfig.taskViewAffiliateGroupEnterOffsetPx)
- .setStartDelay(0)
- .setUpdateListener(null)
- .setInterpolator(mConfig.fastOutLinearInInterpolator)
- .setDuration(mConfig.taskViewExitToAppDuration)
- .start();
+ animate()
+ .alpha(0f)
+ .translationY(
+ getTranslationY() + mConfig.taskViewAffiliateGroupEnterOffsetPx)
+ .setStartDelay(0)
+ .setUpdateListener(null)
+ .setInterpolator(mConfig.fastOutLinearInInterpolator)
+ .setDuration(mConfig.taskViewExitToAppDuration)
+ .start();
}
}
}
@@ -441,23 +468,23 @@
setClipViewInStack(false);
animate().translationX(mConfig.taskViewRemoveAnimTranslationXPx)
- .alpha(0f)
- .setStartDelay(delay)
- .setUpdateListener(null)
- .setInterpolator(mConfig.fastOutSlowInInterpolator)
- .setDuration(mConfig.taskViewRemoveAnimDuration)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- if (r != null) {
- r.run();
- }
+ .alpha(0f)
+ .setStartDelay(delay)
+ .setUpdateListener(null)
+ .setInterpolator(mConfig.fastOutSlowInInterpolator)
+ .setDuration(mConfig.taskViewRemoveAnimDuration)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ if (r != null) {
+ r.run();
+ }
- // Re-enable clipping with the stack (we will reuse this view)
- setClipViewInStack(true);
- }
- })
- .start();
+ // Re-enable clipping with the stack (we will reuse this view)
+ setClipViewInStack(true);
+ }
+ })
+ .start();
}
/** Enables/disables handling touch on this task view. */
@@ -470,12 +497,18 @@
mHeaderView.startNoUserInteractionAnimation();
}
- /** Mark this task view that the user does has not interacted with the stack after a certain time. */
+ /**
+ * Mark this task view that the user does has not interacted with the stack after a certain
+ * time.
+ */
void setNoUserInteractionState() {
mHeaderView.setNoUserInteractionState();
}
- /** Resets the state tracking that the user has not interacted with the stack after a certain time. */
+ /**
+ * Resets the state tracking that the user has not interacted with the stack after a certain
+ * time.
+ */
void resetNoUserInteractionState() {
mHeaderView.resetNoUserInteractionState();
}
@@ -512,6 +545,47 @@
}
}
+ @Override
+ public void dispatchDraw(Canvas canvas) {
+ super.dispatchDraw(canvas);
+ if (mIsFocused) {
+ final int x = getWidth() / 2;
+ final int y = getHeight() / 2;
+ final float hypot = (float) Math.hypot(x, y);
+ final float radius = hypot * mHighlightInCircleRadiusProgress;
+
+ mHighlightPaint.setAlpha(mHighlightInFillAlpha);
+ canvas.drawRect(0, 0, getWidth(), getHeight(), mHighlightPaint);
+
+ mHighlightPaint.setAlpha(mHighlightInCircleAlpha);
+ canvas.drawCircle(x, y, radius, mHighlightPaint);
+ } else {
+ mHighlightPaint.setAlpha(mHighlightOutFillAlpha);
+ canvas.drawRect(0, 0, getWidth(), getHeight(), mHighlightPaint);
+ }
+ }
+
+ public void setHighlightProgress(float progress) {
+ mHighlightProgress = progress;
+ if (mIsFocused) {
+ final float interpolatedProgress = sHighlightInInterpolator.getInterpolation(progress);
+ mHighlightInCircleRadiusProgress =
+ 0.5f + sHighlightInRadiusInterpolator.getInterpolation(progress);
+ mHighlightInCircleAlpha = (int) (mHighlightAlpha * interpolatedProgress);
+ mHighlightInFillAlpha =
+ (mHighlightAlpha / 4) + (int) ((mHighlightAlpha / 2) * interpolatedProgress);
+ } else {
+ final float interpolatedProgress = sHighlightOutInterpolator.getInterpolation(progress);
+ mHighlightOutFillAlpha = (int) (mHighlightAlpha * (1 - interpolatedProgress));
+ }
+
+ invalidate();
+ }
+
+ public float getHighlightProgress() {
+ return mHighlightProgress;
+ }
+
/** Sets the current task progress. */
public void setTaskProgress(float p) {
mTaskProgress = p;
@@ -583,12 +657,13 @@
* if the view is not currently visible, or we are in touch state (where we still want to keep
* track of focus).
*/
- public void setFocusedTask(boolean animateFocusedState) {
- mIsFocused = true;
- if (mFocusAnimationsEnabled) {
- // Focus the header bar
- mHeaderView.onTaskViewFocusChanged(true, animateFocusedState);
+ public void setFocusedTask() {
+ if (mIsFocused) {
+ return;
}
+ mIsFocused = true;
+
+ performFocusAnimation();
// Update the thumbnail alpha with the focus
mThumbnailView.onFocusChanged(true);
// Call the callback
@@ -604,14 +679,31 @@
invalidate();
}
+ private void performFocusAnimation() {
+ if (mFocusAnimationsEnabled) {
+ // Focus the header bar
+ mHeaderView.onTaskViewFocusChanged(true);
+
+ mHighlightAnimator.setDuration(sHighlightInDurationMs);
+ mHighlightAnimator.start();
+ }
+ }
+
/**
* Unsets the focused task explicitly.
*/
void unsetFocusedTask() {
+ if (!mIsFocused) {
+ return;
+ }
+
mIsFocused = false;
if (mFocusAnimationsEnabled) {
// Un-focus the header bar
- mHeaderView.onTaskViewFocusChanged(false, true);
+ mHeaderView.onTaskViewFocusChanged(false);
+
+ mHighlightAnimator.setDuration(sHighlightOutDurationMs);
+ mHighlightAnimator.start();
}
// Update the thumbnail alpha with the focus
@@ -645,9 +737,9 @@
void enableFocusAnimations() {
boolean wasFocusAnimationsEnabled = mFocusAnimationsEnabled;
mFocusAnimationsEnabled = true;
- if (mIsFocused && !wasFocusAnimationsEnabled) {
+ if (mIsFocused) {
// Re-notify the header if we were focused and animations were not previously enabled
- mHeaderView.onTaskViewFocusChanged(true, true);
+ performFocusAnimation();
}
}
@@ -719,7 +811,7 @@
/**** View.OnClickListener Implementation ****/
@Override
- public void onClick(final View v) {
+ public void onClick(final View v) {
final TaskView tv = this;
final boolean delayViewClick = (v != this) && (v != mActionButtonView);
if (delayViewClick) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index 29aef69..cfe5a4e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -5,7 +5,7 @@
* 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
+ * 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,
@@ -42,6 +42,7 @@
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
+
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
@@ -50,13 +51,16 @@
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
-
/* The task bar view */
public class TaskViewHeader extends FrameLayout {
RecentsConfiguration mConfig;
private SystemServicesProxy mSsp;
+ Task mTask;
+ boolean mIsFocused;
+ float mFocusProgress;
+
// Header views
ImageView mMoveTaskButton;
ImageView mDismissButton;
@@ -71,7 +75,7 @@
Drawable mDarkDismissDrawable;
RippleDrawable mBackground;
GradientDrawable mBackgroundColorDrawable;
- AnimatorSet mFocusAnimator;
+ ValueAnimator mFocusAnimator;
String mDismissContentDescription;
// Static highlight that we draw at the top of each view
@@ -123,6 +127,8 @@
sHighlightPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
sHighlightPaint.setAntiAlias(true);
}
+
+ mFocusAnimator = ObjectAnimator.ofFloat(this, "focusProgress", 1f);
}
@Override
@@ -180,14 +186,9 @@
}
}
- /** Returns the secondary color for a primary color. */
- int getSecondaryColor(int primaryColor, boolean useLightOverlayColor) {
- int overlayColor = useLightOverlayColor ? Color.WHITE : Color.BLACK;
- return Utilities.getColorWithOverlay(primaryColor, overlayColor, 0.8f);
- }
-
/** Binds the bar view to the task */
public void rebindToTask(Task t) {
+ mTask = t;
// If an activity icon is defined, then we use that as the primary icon to show in the bar,
// otherwise, we fall back to the application icon
if (t.activityIcon != null) {
@@ -292,7 +293,10 @@
}
}
- /** Mark this task view that the user does has not interacted with the stack after a certain time. */
+ /**
+ * Mark this task view that the user does has not interacted with the stack after a certain
+ * time.
+ */
void setNoUserInteractionState() {
if (mDismissButton.getVisibility() != View.VISIBLE) {
mDismissButton.animate().cancel();
@@ -301,7 +305,10 @@
}
}
- /** Resets the state tracking that the user has not interacted with the stack after a certain time. */
+ /**
+ * Resets the state tracking that the user has not interacted with the stack after a certain
+ * time.
+ */
void resetNoUserInteractionState() {
mDismissButton.setVisibility(View.INVISIBLE);
}
@@ -336,92 +343,43 @@
setLayerType(LAYER_TYPE_NONE, null);
}
+ public void setFocusProgress(float progress) {
+ mFocusProgress = progress;
+ final ArgbEvaluator colorEvaluator = new ArgbEvaluator();
+ int desaturatedColor = calculateDesaurateColor(mBackgroundColor);
+ int color = (Integer) colorEvaluator.evaluate(progress, mBackgroundColor,
+ mIsFocused ? desaturatedColor : mTask.colorPrimary);
+ mBackgroundColorDrawable.setColor(color);
+ mBackgroundColor = color;
+
+ TaskViewHeader.this.setTranslationZ((mIsFocused ? progress : (1 - progress)) * 4);
+ }
+
+ private int calculateDesaurateColor(int saturatedColor) {
+ final float red = 0.2126f * Color.red(saturatedColor);
+ final float green = 0.7152f * Color.green(saturatedColor);
+ final float blue = 0.0722f * Color.blue(saturatedColor);
+ final int sum = (int) (red + green + blue);
+
+ return Color.argb(255, sum, sum, sum);
+ }
+
+ public float getFocusProgress() {
+ return mFocusProgress;
+ }
+
/** Notifies the associated TaskView has been focused. */
- void onTaskViewFocusChanged(boolean focused, boolean animateFocusedState) {
- // If we are not animating the visible state, just return
- if (!animateFocusedState) return;
+ void onTaskViewFocusChanged(final boolean focused) {
+ mIsFocused = focused;
- boolean isRunning = false;
- if (mFocusAnimator != null) {
- isRunning = mFocusAnimator.isRunning();
- Utilities.cancelAnimationWithoutCallbacks(mFocusAnimator);
- }
-
- if (focused) {
- int currentColor = mBackgroundColor;
- int secondaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
- int[][] states = new int[][] {
- new int[] {},
- new int[] { android.R.attr.state_enabled },
- new int[] { android.R.attr.state_pressed }
- };
- int[] newStates = new int[]{
- 0,
- android.R.attr.state_enabled,
- android.R.attr.state_pressed
- };
- int[] colors = new int[] {
- currentColor,
- secondaryColor,
- secondaryColor
- };
- mBackground.setColor(new ColorStateList(states, colors));
- mBackground.setState(newStates);
- // Pulse the background color
- int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
- ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
- currentColor, lightPrimaryColor);
- backgroundColor.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- mBackground.setState(new int[]{});
- }
- });
- backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- int color = (int) animation.getAnimatedValue();
- mBackgroundColorDrawable.setColor(color);
- mBackgroundColor = color;
- }
- });
- backgroundColor.setRepeatCount(ValueAnimator.INFINITE);
- backgroundColor.setRepeatMode(ValueAnimator.REVERSE);
- // Pulse the translation
- ObjectAnimator translation = ObjectAnimator.ofFloat(this, "translationZ", 15f);
- translation.setRepeatCount(ValueAnimator.INFINITE);
- translation.setRepeatMode(ValueAnimator.REVERSE);
-
- mFocusAnimator = new AnimatorSet();
- mFocusAnimator.playTogether(backgroundColor, translation);
- mFocusAnimator.setStartDelay(150);
- mFocusAnimator.setDuration(750);
- mFocusAnimator.start();
- } else {
- if (isRunning) {
- // Restore the background color
- int currentColor = mBackgroundColor;
- ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
- currentColor, mCurrentPrimaryColor);
- backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- int color = (int) animation.getAnimatedValue();
- mBackgroundColorDrawable.setColor(color);
- mBackgroundColor = color;
- }
- });
- // Restore the translation
- ObjectAnimator translation = ObjectAnimator.ofFloat(this, "translationZ", 0f);
-
- mFocusAnimator = new AnimatorSet();
- mFocusAnimator.playTogether(backgroundColor, translation);
- mFocusAnimator.setDuration(150);
- mFocusAnimator.start();
- } else {
- mBackground.setState(new int[] {});
- setTranslationZ(0f);
- }
- }
+ mFocusAnimator.setDuration(
+ mIsFocused ?
+ TaskView.sHighlightInDurationMs :
+ TaskView.sHighlightOutDurationMs);
+ mFocusAnimator.setInterpolator(
+ mIsFocused ?
+ TaskView.sHighlightInRadiusInterpolator :
+ TaskView.sHighlightOutInterpolator);
+ mFocusAnimator.start();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index 117a7d3..d5862bc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -18,7 +18,9 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
+import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
@@ -32,6 +34,11 @@
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
+import android.view.animation.DecelerateInterpolator;
+import android.view.animation.Interpolator;
+import android.view.animation.OvershootInterpolator;
+
+import com.android.systemui.R;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
@@ -57,8 +64,8 @@
// Thumbnail alpha
float mThumbnailAlpha;
ValueAnimator mThumbnailAlphaAnimator;
- ValueAnimator.AnimatorUpdateListener mThumbnailAlphaUpdateListener
- = new ValueAnimator.AnimatorUpdateListener() {
+ ValueAnimator.AnimatorUpdateListener mThumbnailAlphaUpdateListener =
+ new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mThumbnailAlpha = (float) animation.getAnimatedValue();