am 6697322a: Merge "Should use Activity.onEnterAnimationComplete. (Bug 18031283)" into lmp-mr1-dev

* commit '6697322af724d44ee59259d4f5563b07c24f62b4':
  Should use Activity.onEnterAnimationComplete. (Bug 18031283)
This commit is contained in:
Winson Chung
2014-10-24 18:30:33 +00:00
committed by Android Git Automerger
9 changed files with 202 additions and 256 deletions

View File

@@ -239,7 +239,7 @@
<dimen name="recents_search_bar_space_height">64dp</dimen>
<!-- The side padding for the task stack as a percentage of the width. -->
<item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.04444</item>
<item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.03333</item>
<!-- The overscroll percentage allowed on the stack. -->
<item name="recents_stack_overscroll_percentage" format="float" type="dimen">0.0875</item>

View File

@@ -54,7 +54,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/** A proxy implementation for the recents component */
public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener {
public class AlternateRecentsComponent {
final public static String EXTRA_FROM_HOME = "recents.triggeredOverHome";
final public static String EXTRA_FROM_SEARCH_HOME = "recents.triggeredOverSearchHome";
@@ -63,7 +63,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "recents.triggeredFromAltTab";
final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "recents.triggeredFromHomeKey";
final public static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
final public static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
final public static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
@@ -78,9 +77,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
Context mContext;
LayoutInflater mInflater;
SystemServicesProxy mSystemServicesProxy;
Handler mHandler;
boolean mBootCompleted;
boolean mStartAnimationTriggered;
// Task launching
RecentsConfiguration mConfig;
@@ -106,7 +103,6 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
mInflater = LayoutInflater.from(context);
mContext = context;
mSystemServicesProxy = new SystemServicesProxy(context);
mHandler = new Handler();
mTaskStackBounds = new Rect();
}
@@ -364,30 +360,27 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
* Creates the activity options for a unknown state->recents transition.
*/
ActivityOptions getUnknownTransitionActivityOptions() {
mStartAnimationTriggered = false;
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_unknown_enter,
R.anim.recents_from_unknown_exit, mHandler, this);
R.anim.recents_from_unknown_exit);
}
/**
* Creates the activity options for a home->recents transition.
*/
ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) {
mStartAnimationTriggered = false;
if (fromSearchHome) {
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_search_launcher_enter,
R.anim.recents_from_search_launcher_exit, mHandler, this);
R.anim.recents_from_search_launcher_exit);
}
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_launcher_enter,
R.anim.recents_from_launcher_exit, mHandler, this);
R.anim.recents_from_launcher_exit);
}
/**
* Creates the activity options for an app->recents transition. If this method sets the static
* screenshot, then we will use that for the transition.
* Creates the activity options for an app->recents transition.
*/
ActivityOptions getThumbnailTransitionActivityOptions(ActivityManager.RunningTaskInfo topTask,
boolean isTopTaskHome) {
@@ -411,10 +404,9 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
c.setBitmap(null);
}
mStartAnimationTriggered = false;
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
toTaskRect.height(), this);
toTaskRect.height(), null);
}
// If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -551,42 +543,4 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
sRecentsComponentCallbacks.onVisibilityChanged(visible);
}
}
/**** OnAnimationStartedListener Implementation ****/
@Override
public void onAnimationStarted() {
// Notify recents to start the enter animation
if (!mStartAnimationTriggered) {
// There can be a race condition between the start animation callback and
// the start of the new activity (where we register the receiver that listens
// to this broadcast, so we add our own receiver and if that gets called, then
// we know the activity has not yet started and we can retry sending the broadcast.
BroadcastReceiver fallbackReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() == Activity.RESULT_OK) {
mStartAnimationTriggered = true;
return;
}
// Schedule for the broadcast to be sent again after some time
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
onAnimationStarted();
}
}, 75);
}
};
// Send the broadcast to notify Recents that the animation has started
Intent intent = new Intent(ACTION_START_ENTER_ANIMATION);
intent.setPackage(mContext.getPackageName());
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
fallbackReceiver, null, Activity.RESULT_CANCELED, null, null);
}
}
}

View File

@@ -141,14 +141,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
} else if (action.equals(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
// If we are toggling Recents, then first unfilter any filtered stacks first
dismissRecentsToFocusedTaskOrHome(true);
} else if (action.equals(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION)) {
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(context, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
onEnterAnimationTriggered();
// Notify the fallback receiver that we have successfully got the broadcast
// See AlternateRecentsComponent.onAnimationStarted()
setResultCode(Activity.RESULT_OK);
}
}
};
@@ -441,7 +433,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
onEnterAnimationTriggered();
// Animate the SystemUI scrim views
mScrimViews.startEnterRecentsAnimation();
}
@Override
@@ -469,7 +462,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
IntentFilter filter = new IntentFilter();
filter.addAction(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY);
filter.addAction(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY);
filter.addAction(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION);
registerReceiver(mServiceBroadcastReceiver, filter);
// Register any broadcast receivers for the task loader
@@ -511,6 +503,16 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
@Override
public void onEnterAnimationComplete() {
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
// Animate the SystemUI scrim views
mScrimViews.startEnterRecentsAnimation();
}
@Override
public void onTrimMemory(int level) {
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -592,12 +594,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
/** Called when the enter recents animation is triggered. */
public void onEnterAnimationTriggered() {
// Animate the SystemUI scrim views
mScrimViews.startEnterRecentsAnimation();
}
/**** RecentsView.RecentsViewCallbacks Implementation ****/
@Override

View File

@@ -16,6 +16,7 @@
package com.android.systemui.recents.misc;
import android.animation.Animator;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Matrix;
@@ -188,4 +189,15 @@ public class Utilities {
int flags = intent.getFlags();
return (flags & Intent.FLAG_ACTIVITY_NEW_DOCUMENT) == Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
}
/**
* Cancels an animation ensuring that if it has listeners, onCancel and onEnd
* are not called.
*/
public static void cancelAnimationWithoutCallbacks(Animator animator) {
if (animator != null) {
animator.removeAllListeners();
animator.cancel();
}
}
}

View File

@@ -68,7 +68,7 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
mSourceView.invalidateOutline();
updateClipBounds();
if (!mConfig.useHardwareLayers) {
mSourceView.mThumbnailView.updateVisibility(
mSourceView.mThumbnailView.updateThumbnailVisibility(
bottom - mSourceView.getPaddingBottom());
}
}

View File

@@ -23,6 +23,7 @@ import android.animation.ValueAnimator;
import android.content.Context;
import android.widget.OverScroller;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
/* The scrolling logic for a TaskStackView */
public class TaskStackViewScroller {
@@ -161,10 +162,7 @@ public class TaskStackViewScroller {
/** Aborts any current stack scrolls */
void stopBoundScrollAnimation() {
if (mScrollAnimator != null) {
mScrollAnimator.removeAllListeners();
mScrollAnimator.cancel();
}
Utilities.cancelAnimationWithoutCallbacks(mScrollAnimator);
}
/**** OverScroller ****/

View File

@@ -28,10 +28,9 @@ import android.view.ViewPropertyAnimator;
import android.view.animation.AccelerateInterpolator;
import android.widget.FrameLayout;
import com.android.systemui.R;
import com.android.systemui.recents.AlternateRecentsComponent;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -53,11 +52,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
float mTaskProgress;
ObjectAnimator mTaskProgressAnimator;
ObjectAnimator mDimAnimator;
float mMaxDimScale;
int mDim;
int mDimAlpha;
AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1f);
PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.MULTIPLY);
PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
Paint mDimLayerPaint = new Paint();
Task mTask;
boolean mTaskDataLoaded;
@@ -65,7 +64,6 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
boolean mFocusAnimationsEnabled;
boolean mClipViewInStack;
AnimateableViewBounds mViewBounds;
Paint mLayerPaint = new Paint();
View mContent;
TaskViewThumbnail mThumbnailView;
@@ -130,7 +128,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mContent = findViewById(R.id.task_view_content);
mHeaderView = (TaskViewHeader) findViewById(R.id.task_view_bar);
mThumbnailView = (TaskViewThumbnail) findViewById(R.id.task_view_thumbnail);
mThumbnailView.enableTaskBarClip(mHeaderView);
mThumbnailView.updateClipToTaskBar(mHeaderView);
mActionButtonView = findViewById(R.id.lock_to_app_fab);
mActionButtonView.setOutlineProvider(new ViewOutlineProvider() {
@Override
@@ -179,10 +177,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
!mConfig.fakeShadows, updateCallback);
// Update the task progress
if (mTaskProgressAnimator != null) {
mTaskProgressAnimator.removeAllListeners();
mTaskProgressAnimator.cancel();
}
Utilities.cancelAnimationWithoutCallbacks(mTaskProgressAnimator);
if (duration <= 0) {
setTaskProgress(toTransform.p);
} else {
@@ -377,7 +372,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mThumbnailView.startLaunchTaskAnimation(postAnimRunnable);
// Animate the dim
if (mDim > 0) {
if (mDimAlpha > 0) {
ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
anim.setDuration(mConfig.taskBarExitAnimDuration);
anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
@@ -495,26 +490,16 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Returns the current dim. */
public void setDim(int dim) {
mDim = dim;
if (mDimAnimator != null) {
mDimAnimator.removeAllListeners();
mDimAnimator.cancel();
}
mDimAlpha = dim;
if (mConfig.useHardwareLayers) {
// Defer setting hardware layers if we have not yet measured, or there is no dim to draw
if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0) {
if (mDimAnimator != null) {
mDimAnimator.removeAllListeners();
mDimAnimator.cancel();
}
int inverse = 255 - mDim;
mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
mLayerPaint.setColorFilter(mDimColorFilter);
mContent.setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
mDimColorFilter.setColor(Color.argb(mDimAlpha, 0, 0, 0));
mDimLayerPaint.setColorFilter(mDimColorFilter);
mContent.setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
}
} else {
float dimAlpha = mDim / 255.0f;
float dimAlpha = mDimAlpha / 255.0f;
if (mThumbnailView != null) {
mThumbnailView.setDimAlpha(dimAlpha);
}
@@ -526,7 +511,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Returns the current dim. */
public int getDim() {
return mDim;
return mDimAlpha;
}
/** Animates the dim to the task progress. */

View File

@@ -36,7 +36,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -56,23 +55,27 @@ public class TaskViewHeader extends FrameLayout {
RecentsConfiguration mConfig;
// Header views
ImageView mDismissButton;
ImageView mApplicationIcon;
TextView mActivityDescription;
RippleDrawable mBackground;
GradientDrawable mBackgroundColorDrawable;
// Header drawables
boolean mCurrentPrimaryColorIsDark;
int mCurrentPrimaryColor;
int mBackgroundColor;
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
RippleDrawable mBackground;
GradientDrawable mBackgroundColorDrawable;
AnimatorSet mFocusAnimator;
PorterDuffColorFilter mDimFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
boolean mCurrentPrimaryColorIsDark;
int mCurrentPrimaryColor;
// Static highlight that we draw at the top of each view
static Paint sHighlightPaint;
private Paint mDimPaint = new Paint();
// Header dim, which is only used when task view hardware layers are not used
Paint mDimLayerPaint = new Paint();
PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
public TaskViewHeader(Context context) {
this(context, null);
@@ -172,6 +175,16 @@ public class TaskViewHeader extends FrameLayout {
return false;
}
/**
* Sets the dim alpha, only used when we are not using hardware layers.
* (see RecentsConfiguration.useHardwareLayers)
*/
void setDimAlpha(int alpha) {
mDimColorFilter.setColor(Color.argb(alpha, 0, 0, 0));
mDimLayerPaint.setColorFilter(mDimColorFilter);
setLayerType(LAYER_TYPE_HARDWARE, mDimLayerPaint);
}
/** Returns the secondary color for a primary color. */
int getSecondaryColor(int primaryColor, boolean useLightOverlayColor) {
int overlayColor = useLightOverlayColor ? Color.WHITE : Color.BLACK;
@@ -266,8 +279,7 @@ public class TaskViewHeader extends FrameLayout {
boolean isRunning = false;
if (mFocusAnimator != null) {
isRunning = mFocusAnimator.isRunning();
mFocusAnimator.removeAllListeners();
mFocusAnimator.cancel();
Utilities.cancelAnimationWithoutCallbacks(mFocusAnimator);
}
if (focused) {
@@ -344,11 +356,4 @@ public class TaskViewHeader extends FrameLayout {
}
}
}
public void setDimAlpha(int alpha) {
int color = Color.argb(alpha, 0, 0, 0);
mDimFilter.setColor(color);
mDimPaint.setColorFilter(mDimFilter);
setLayerType(LAYER_TYPE_HARDWARE, mDimPaint);
}
}

View File

@@ -33,37 +33,48 @@ import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
/** The task thumbnail view */
/**
* The task thumbnail view. It implements an image view that allows for animating the dim and
* alpha of the thumbnail image.
*/
public class TaskViewThumbnail extends View {
private final int mCornerRadius;
private final Matrix mScaleMatrix = new Matrix();
RecentsConfiguration mConfig;
// Task bar clipping
Rect mClipRect = new Rect();
// Drawing
float mDimAlpha;
Matrix mScaleMatrix = new Matrix();
Paint mDrawPaint = new Paint();
RectF mBitmapRect = new RectF();
RectF mLayoutRect = new RectF();
BitmapShader mBitmapShader;
LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0);
private final RectF mBitmapRect = new RectF();
private final RectF mLayoutRect = new RectF();
private BitmapShader mBitmapShader;
private float mBitmapAlpha;
private float mDimAlpha;
private View mTaskBar;
private boolean mInvisible;
private ValueAnimator mAlphaAnimator;
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
// Thumbnail alpha
float mThumbnailAlpha;
ValueAnimator mThumbnailAlphaAnimator;
ValueAnimator.AnimatorUpdateListener mThumbnailAlphaUpdateListener
= new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mBitmapAlpha = (float) animation.getAnimatedValue();
updateFilter();
mThumbnailAlpha = (float) animation.getAnimatedValue();
updateThumbnailPaintFilter();
}
};
// Task bar clipping, the top of this thumbnail can be clipped against the opaque header
// bar that overlaps this thumbnail
View mTaskBar;
Rect mClipRect = new Rect();
// Visibility optimization, if the thumbnail height is less than the height of the header
// bar for the task view, then just mark this thumbnail view as invisible
boolean mInvisible;
public TaskViewThumbnail(Context context) {
this(context, null);
}
@@ -79,103 +90,15 @@ public class TaskViewThumbnail extends View {
public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mConfig = RecentsConfiguration.getInstance();
mCornerRadius = mConfig.taskViewRoundedCornerRadiusPx;
mDrawPaint.setColorFilter(mLightingColorFilter);
mDrawPaint.setFilterBitmap(true);
mDrawPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
if (mInvisible) {
return;
}
canvas.drawRoundRect(0,
0,
getWidth(),
getHeight(),
mCornerRadius,
mCornerRadius,
mDrawPaint);
}
@Override
protected void onFinishInflate() {
mBitmapAlpha = 0.9f;
updateFilter();
}
private void updateFilter() {
if (mInvisible) {
return;
}
int mul = (int) ((1.0f - mDimAlpha) * mBitmapAlpha * 255);
int add = (int) ((1.0f - mDimAlpha) * (1 - mBitmapAlpha) * 255);
if (mBitmapShader != null) {
mLightingColorFilter.setColorMultiply(Color.argb(255, mul, mul, mul));
mLightingColorFilter.setColorAdd(Color.argb(0, add, add, add));
mDrawPaint.setColorFilter(mLightingColorFilter);
mDrawPaint.setColor(0xffffffff);
} else {
mDrawPaint.setColorFilter(null);
int grey = mul + add;
mDrawPaint.setColor(Color.argb(255, grey, grey, grey));
}
invalidate();
}
/** Updates the clip rect based on the given task bar. */
void enableTaskBarClip(View taskBar) {
mTaskBar = taskBar;
int top = (int) Math.max(0, taskBar.getTranslationY() +
taskBar.getMeasuredHeight() - 1);
mClipRect.set(0, top, getMeasuredWidth(), getMeasuredHeight());
setClipBounds(mClipRect);
}
void updateVisibility(int clipBottom) {
boolean invisible = mTaskBar != null && getHeight() - clipBottom < mTaskBar.getHeight();
if (invisible != mInvisible) {
mInvisible = invisible;
if (!mInvisible) {
updateFilter();
}
invalidate();
}
}
/** Binds the thumbnail view to the screenshot. */
boolean bindToScreenshot(Bitmap ss) {
setImageBitmap(ss);
return ss != null;
}
/** Unbinds the thumbnail view from the screenshot. */
void unbindFromScreenshot() {
setImageBitmap(null);
}
/** Binds the thumbnail view to the task */
void rebindToTask(Task t) {
if (t.thumbnail != null) {
setImageBitmap(t.thumbnail);
} else {
setImageBitmap(null);
}
}
public void setImageBitmap(Bitmap bm) {
if (bm != null) {
mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
mDrawPaint.setShader(mBitmapShader);
mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight());
updateBitmapScale();
} else {
mBitmapShader = null;
mDrawPaint.setShader(null);
}
updateFilter();
mThumbnailAlpha = mConfig.taskViewThumbnailAlpha;
updateThumbnailPaintFilter();
}
@Override
@@ -183,25 +106,106 @@ public class TaskViewThumbnail extends View {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
mLayoutRect.set(0, 0, getWidth(), getHeight());
updateBitmapScale();
updateThumbnailScale();
}
}
private void updateBitmapScale() {
@Override
protected void onDraw(Canvas canvas) {
if (mInvisible) {
return;
}
// Draw the thumbnail with the rounded corners
canvas.drawRoundRect(0, 0, getWidth(), getHeight(),
mConfig.taskViewRoundedCornerRadiusPx,
mConfig.taskViewRoundedCornerRadiusPx, mDrawPaint);
}
/** Sets the thumbnail to a given bitmap. */
void setThumbnail(Bitmap bm) {
if (bm != null) {
mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP);
mDrawPaint.setShader(mBitmapShader);
mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight());
updateThumbnailScale();
} else {
mBitmapShader = null;
mDrawPaint.setShader(null);
}
updateThumbnailPaintFilter();
}
/** Updates the paint to draw the thumbnail. */
void updateThumbnailPaintFilter() {
if (mInvisible) {
return;
}
int mul = (int) ((1.0f - mDimAlpha) * mThumbnailAlpha * 255);
int add = (int) ((1.0f - mDimAlpha) * (1 - mThumbnailAlpha) * 255);
if (mBitmapShader != null) {
mLightingColorFilter.setColorMultiply(Color.argb(255, mul, mul, mul));
mLightingColorFilter.setColorAdd(Color.argb(0, add, add, add));
mDrawPaint.setColorFilter(mLightingColorFilter);
mDrawPaint.setColor(0xffffffff);
} else {
int grey = mul + add;
mDrawPaint.setColorFilter(null);
mDrawPaint.setColor(Color.argb(255, grey, grey, grey));
}
invalidate();
}
/** Updates the thumbnail shader's scale transform. */
void updateThumbnailScale() {
if (mBitmapShader != null) {
mScaleMatrix.setRectToRect(mBitmapRect, mLayoutRect, Matrix.ScaleToFit.FILL);
mBitmapShader.setLocalMatrix(mScaleMatrix);
}
}
/** Updates the clip rect based on the given task bar. */
void updateClipToTaskBar(View taskBar) {
mTaskBar = taskBar;
int top = (int) Math.max(0, taskBar.getTranslationY() +
taskBar.getMeasuredHeight() - 1);
mClipRect.set(0, top, getMeasuredWidth(), getMeasuredHeight());
setClipBounds(mClipRect);
}
/** Updates the visibility of the the thumbnail. */
void updateThumbnailVisibility(int clipBottom) {
boolean invisible = mTaskBar != null && (getHeight() - clipBottom) <= mTaskBar.getHeight();
if (invisible != mInvisible) {
mInvisible = invisible;
if (!mInvisible) {
updateThumbnailPaintFilter();
}
invalidate();
}
}
/**
* Sets the dim alpha, only used when we are not using hardware layers.
* (see RecentsConfiguration.useHardwareLayers)
*/
public void setDimAlpha(float dimAlpha) {
mDimAlpha = dimAlpha;
updateFilter();
updateThumbnailPaintFilter();
}
/** Binds the thumbnail view to the task */
void rebindToTask(Task t) {
if (t.thumbnail != null) {
setThumbnail(t.thumbnail);
} else {
setThumbnail(null);
}
}
/** Unbinds the thumbnail view from the task */
void unbindFromTask() {
setImageBitmap(null);
setThumbnail(null);
}
/** Handles focus changes. */
@@ -217,54 +221,46 @@ public class TaskViewThumbnail extends View {
}
}
/** Prepares for the enter recents animation. */
/**
* Prepares for the enter recents animation, this gets called before the the view
* is first visible and will be followed by a startEnterRecentsAnimation() call.
*/
void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask) {
if (isTaskViewLaunchTargetTask) {
mBitmapAlpha = 1f;
mThumbnailAlpha = 1f;
} else {
mBitmapAlpha = mConfig.taskViewThumbnailAlpha;
mThumbnailAlpha = mConfig.taskViewThumbnailAlpha;
}
updateFilter();
updateThumbnailPaintFilter();
}
/** Animates this task thumbnail as it enters recents */
/** Animates this task thumbnail as it enters Recents. */
void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
startFadeAnimation(mConfig.taskViewThumbnailAlpha, delay,
mConfig.taskBarEnterAnimDuration, postAnimRunnable);
}
/** Animates this task thumbnail as it exits recents */
/** Animates this task thumbnail as it exits Recents. */
void startLaunchTaskAnimation(Runnable postAnimRunnable) {
startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable);
}
/** Animates the thumbnail alpha. */
/** Starts a new thumbnail alpha animation. */
void startFadeAnimation(float finalAlpha, int delay, int duration, final Runnable postAnimRunnable) {
if (mAlphaAnimator != null) {
mAlphaAnimator.cancel();
}
mAlphaAnimator = ValueAnimator.ofFloat(mBitmapAlpha, finalAlpha);
mAlphaAnimator.addUpdateListener(mAlphaUpdateListener);
mAlphaAnimator.setStartDelay(delay);
mAlphaAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
mAlphaAnimator.setDuration(duration);
mAlphaAnimator.start();
Utilities.cancelAnimationWithoutCallbacks(mThumbnailAlphaAnimator);
mThumbnailAlphaAnimator = ValueAnimator.ofFloat(mThumbnailAlpha, finalAlpha);
mThumbnailAlphaAnimator.setStartDelay(delay);
mThumbnailAlphaAnimator.setDuration(duration);
mThumbnailAlphaAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
mThumbnailAlphaAnimator.addUpdateListener(mThumbnailAlphaUpdateListener);
if (postAnimRunnable != null) {
mAlphaAnimator.addListener(new AnimatorListenerAdapter() {
public boolean mCancelled;
@Override
public void onAnimationCancel(Animator animation) {
mCancelled = true;
}
mThumbnailAlphaAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (!mCancelled) {
postAnimRunnable.run();
}
postAnimRunnable.run();
}
});
}
mThumbnailAlphaAnimator.start();
}
}