import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
+import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
boolean mIsFullscreen;
- Paint mLayerPaint = new Paint();
static Paint sHighlightPaint;
public TaskBarView(Context context) {
mActivityDescription.setText(t.activityLabel);
}
// Try and apply the system ui tint
- setBackgroundColor(t.colorPrimary);
+ int existingBgColor = (getBackground() instanceof ColorDrawable) ?
+ ((ColorDrawable) getBackground()).getColor() : 0;
+ if (existingBgColor != t.colorPrimary) {
+ setBackgroundColor(t.colorPrimary);
+ }
mActivityDescription.setTextColor(t.useLightOnPrimaryColor ?
mConfig.taskBarViewLightTextColor : mConfig.taskBarViewDarkTextColor);
mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
mDismissButton.setAlpha(1f);
}
}
-
- /** Enable the hw layers on this task view */
- void enableHwLayers() {
- mDismissButton.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
- }
-
- /** Disable the hw layers on this task view */
- void disableHwLayers() {
- mDismissButton.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
- }
}
LayoutInflater mInflater;
// A convenience runnable to return all views to the pool
- // XXX: After this is set, we should mark this task stack view as disabled and check that in synchronize model
Runnable mReturnAllViewsToPoolRunnable = new Runnable() {
@Override
public void run() {
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
- mViewPool.returnViewToPool((TaskView) getChildAt(i));
+ TaskView tv = (TaskView) getChildAt(i);
+ mViewPool.returnViewToPool(tv);
+ // Also hide the view since we don't need it anymore
+ tv.setVisibility(View.INVISIBLE);
}
}
};
}
}
});
- mHwLayersTrigger = new ReferenceCountedTrigger(getContext(), new Runnable() {
- @Override
- public void run() {
- // Enable hw layers on each of the children
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- TaskView tv = (TaskView) getChildAt(i);
- tv.enableHwLayers();
- }
- }
- }, new Runnable() {
- @Override
- public void run() {
- // Disable hw layers on each of the children
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- TaskView tv = (TaskView) getChildAt(i);
- tv.disableHwLayers();
- }
- }
- }, new Runnable() {
- @Override
- public void run() {
- new Throwable("Invalid hw layers ref count").printStackTrace();
- Console.logError(getContext(), "Invalid HW layers ref count");
- }
- });
}
/** Sets the callbacks */
int curScroll = getStackScroll();
int newScroll = Math.max(mMinScroll, Math.min(mMaxScroll, curScroll));
if (newScroll != curScroll) {
- // Enable hw layers on the stack
- addHwLayersRefCount("animateBoundScroll");
-
// Start a new scroll animation
- animateScroll(curScroll, newScroll, new Runnable() {
- @Override
- public void run() {
- // Disable hw layers on the stack
- decHwLayersRefCount("animateBoundScroll");
- }
- });
+ animateScroll(curScroll, newScroll, null);
}
return mScrollAnimator;
}
if (!mScroller.isFinished()) {
// Abort the scroller
mScroller.abortAnimation();
- // And disable hw layers on the stack
- decHwLayersRefCount("flingScroll");
}
}
focusTask(mFocusedTaskIndex, true);
}
- /** Enables the hw layers and increments the hw layer requirement ref count */
- void addHwLayersRefCount(String reason) {
- mHwLayersTrigger.increment();
- }
-
- /** Decrements the hw layer requirement ref count and disables the hw layers when we don't
- need them anymore. */
- void decHwLayersRefCount(String reason) {
- mHwLayersTrigger.decrement();
- }
-
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mTouchHandler.onInterceptTouchEvent(ev);
if (mScroller.computeScrollOffset()) {
setStackScroll(mScroller.getCurrY());
invalidate();
-
- // If we just finished scrolling, then disable the hw layers
- if (mScroller.isFinished()) {
- decHwLayersRefCount("finishedFlingScroll");
- }
}
}
// Detach the view from the hierarchy
detachViewFromParent(tv);
- // Disable HW layers
- tv.disableHwLayers();
-
// Reset the view properties
tv.resetViewProperties();
}
} else {
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
}
-
- // Enable hw layers on this view if hw layers are enabled on the stack
- if (mHwLayersTrigger.getCount() > 0) {
- tv.enableHwLayers();
- }
}
@Override
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
- // Enable HW layers
- mSv.addHwLayersRefCount("stackScroll");
}
mLastMotionX = x;
case MotionEvent.ACTION_UP: {
// Animate the scroll back if we've cancelled
mSv.animateBoundScroll();
- // Disable HW layers
- if (mIsScrolling) {
- mSv.decHwLayersRefCount("stackScroll");
- }
// Reset the drag state and the velocity tracker
mIsScrolling = false;
mActivePointerId = INACTIVE_POINTER_ID;
if (parent != null) {
parent.requestDisallowInterceptTouchEvent(true);
}
- // Enable HW layers
- mSv.addHwLayersRefCount("stackScroll");
}
}
if (mIsScrolling) {
int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
- // Enable HW layers on the stack
- mSv.addHwLayersRefCount("flingScroll");
// XXX: Make this animation a function of the velocity AND distance
int overscrollRange = (int) (Math.min(1f,
Math.abs((float) velocity / mMaximumVelocity)) *
mSv.animateBoundScroll();
}
- if (mIsScrolling) {
- // Disable HW layers
- mSv.decHwLayersRefCount("stackScroll");
- }
mActivePointerId = INACTIVE_POINTER_ID;
mIsScrolling = false;
mTotalScrollMotion = 0;
break;
}
case MotionEvent.ACTION_CANCEL: {
- if (mIsScrolling) {
- // Disable HW layers
- mSv.decHwLayersRefCount("stackScroll");
- }
if (mSv.isScrollOutOfBounds()) {
// Animate the scroll back into bounds
// XXX: Make this animation a function of the velocity OR distance
TaskView tv = (TaskView) v;
// Disable clipping with the stack while we are swiping
tv.setClipViewInStack(false);
- // Enable HW layers on that task
- tv.enableHwLayers();
// Disallow touch events from this task view
tv.setTouchEnabled(false);
// Hide the footer
@Override
public void onChildDismissed(View v) {
TaskView tv = (TaskView) v;
- // Disable HW layers on that task
- if (mSv.mHwLayersTrigger.getCount() == 0) {
- tv.disableHwLayers();
- }
// Re-enable clipping with the stack (we will reuse this view)
tv.setClipViewInStack(true);
// Re-enable touch events from this task view
@Override
public void onSnapBackCompleted(View v) {
TaskView tv = (TaskView) v;
- // Disable HW layers on that task
- if (mSv.mHwLayersTrigger.getCount() == 0) {
- tv.disableHwLayers();
- }
// Re-enable clipping with the stack
tv.setClipViewInStack(true);
// Re-enable touch events from this task view
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Paint;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.model.Task;
-// XXX: In debug mode, we should override invalidate() and check the layout type (do this in TaskStackView as well)
-
/* A task view */
public class TaskView extends FrameLayout implements Task.TaskCallbacks,
TaskFooterView.TaskFooterViewCallbacks, View.OnClickListener, View.OnLongClickListener {
int mDim;
int mMaxDim;
AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator();
+ PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.MULTIPLY);
Task mTask;
boolean mTaskDataLoaded;
mMaxDim = mConfig.taskStackMaxDim;
mClipViewInStack = true;
mViewBounds = new AnimateableViewBounds(this, mConfig.taskViewRoundedCornerRadiusPx);
- setWillNotDraw(false);
- setDim(getDim());
setOutlineProvider(mViewBounds);
+ setDim(getDim());
}
/** Set callback */
}
// Apply the transform
- toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator,
+ toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator, false,
mUpdateDimListener);
}
AlternateRecentsComponent.consumeLastScreenshot();
}
})
- .withLayer()
.start();
} else {
// Otherwise, just enable the thumbnail clip
.setUpdateListener(null)
.setInterpolator(mConfig.quintOutInterpolator)
.setDuration(mConfig.taskViewEnterFromHomeDuration)
- .withLayer()
.withEndAction(new Runnable() {
@Override
public void run() {
.setUpdateListener(null)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
.setDuration(mConfig.taskViewExitToHomeDuration)
- .withLayer()
.withEndAction(ctx.postAnimationTrigger.decrementAsRunnable())
.start();
ctx.postAnimationTrigger.increment();
.setUpdateListener(null)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(mConfig.taskViewRemoveAnimDuration)
- .withLayer()
.withEndAction(new Runnable() {
@Override
public void run() {
/** Returns the current dim. */
public void setDim(int dim) {
mDim = dim;
- postInvalidateOnAnimation();
+ int inverse = 255 - mDim;
+ mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
+ mLayerPaint.setColorFilter(mDimColorFilter);
+ setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
}
/** Returns the current dim. */
/**** View drawing ****/
@Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
-
- // Apply the dim if necessary
- if (mDim > 0) {
- canvas.drawColor(mDim << 24);
- }
- }
-
- @Override
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
if (mIsStub && (child != mBarView)) {
// Skip the thumbnail view if we are in stub mode
return super.drawChild(canvas, child, drawingTime);
}
- /** Enable the hw layers on this task view */
- void enableHwLayers() {
- mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
- mBarView.enableHwLayers();
- mFooterView.setLayerType(View.LAYER_TYPE_HARDWARE, mLayerPaint);
- }
-
- /** Disable the hw layers on this task view */
- void disableHwLayers() {
- mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
- mBarView.disableHwLayers();
- mFooterView.setLayerType(View.LAYER_TYPE_NONE, mLayerPaint);
- }
-
/**** View focus state ****/
/**
/**** View.OnClickListener Implementation ****/
@Override
- public void onClick(final View v) {
+ public void onClick(final View v) {
// We purposely post the handler delayed to allow for the touch feedback to draw
final TaskView tv = this;
postDelayed(new Runnable() {
}
/** Applies this transform to a view. */
- public void applyToTaskView(View v, int duration, Interpolator interp,
+ public void applyToTaskView(View v, int duration, Interpolator interp, boolean allowLayers,
ValueAnimator.AnimatorUpdateListener scaleUpdateListener) {
// Check to see if any properties have changed, and update the task view
if (duration > 0) {
ViewPropertyAnimator anim = v.animate();
- boolean useLayers = false;
+ boolean requiresLayers = false;
// Animate to the final state
if (hasTranslationYChangedFrom(v.getTranslationY())) {
anim.scaleX(scale)
.scaleY(scale)
.setUpdateListener(scaleUpdateListener);
- useLayers = true;
+ requiresLayers = true;
}
if (hasAlphaChangedFrom(v.getAlpha())) {
// Use layers if we animate alpha
anim.alpha(alpha);
- useLayers = true;
+ requiresLayers = true;
}
- if (useLayers) {
+ if (requiresLayers && allowLayers) {
anim.withLayer();
}
anim.setStartDelay(startDelay)
v.setScaleX(1f);
v.setScaleY(1f);
v.setAlpha(1f);
- v.invalidate();
}
@Override