Merge "Removed round rect clipping and hardware layers from recents" into lmp-dev

This commit is contained in:
Selim Cinek
2014-09-18 18:33:25 +00:00
committed by Android (Google) Code Review
9 changed files with 218 additions and 52 deletions

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:topLeftRadius="@dimen/recents_task_view_rounded_corners_radius"
android:topRightRadius="@dimen/recents_task_view_rounded_corners_radius"/>
<solid android:color="#00000000" />
</shape>

View File

@@ -15,10 +15,9 @@
-->
<com.android.systemui.recents.views.TaskView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
android:background="#FFffffff">
android:focusable="true">
<com.android.systemui.recents.views.TaskViewThumbnail
android:id="@+id/task_view_thumbnail"
android:layout_width="match_parent"

View File

@@ -29,6 +29,10 @@
ImageView -->
<bool name="config_recents_thumbnail_image_fits_to_xy">false</bool>
<!-- Whether recents should use hardware layers for its taskviews. This flag can be enabled
for devices where the java drawing of round rects may be slow -->
<bool name="config_recents_use_hardware_layers">false</bool>
<!-- The number of app thumbnails we keep in memory -->
<integer name="config_recents_max_thumbnail_count">10</integer>

View File

@@ -119,6 +119,7 @@ public class RecentsConfiguration {
public int launchedToTaskId;
/** Misc **/
public boolean useHardwareLayers;
public int altTabKeyDelay;
/** Dev options and global settings */
@@ -271,6 +272,7 @@ public class RecentsConfiguration {
res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration);
// Misc
useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers);
altTabKeyDelay = res.getInteger(R.integer.recents_alt_tab_key_delay);
}

View File

@@ -204,7 +204,8 @@ class TaskResourceLoader implements Runnable {
if (!mCancelled) {
// Notify that the task data has changed
final Drawable newIcon = cachedIcon;
final Bitmap newThumbnail = cachedThumbnail;
final Bitmap newThumbnail = cachedThumbnail == mDefaultThumbnail
? null : cachedThumbnail;
mMainThreadHandler.post(new Runnable() {
@Override
public void run() {
@@ -252,7 +253,6 @@ public class RecentsTaskLoader {
BitmapDrawable mDefaultApplicationIcon;
Bitmap mDefaultThumbnail;
Bitmap mLoadingThumbnail;
/** Private Constructor */
private RecentsTaskLoader(Context context) {
@@ -271,9 +271,6 @@ public class RecentsTaskLoader {
mDefaultThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
mDefaultThumbnail.setHasAlpha(false);
mDefaultThumbnail.eraseColor(0xFFffffff);
mLoadingThumbnail = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
mLoadingThumbnail.setHasAlpha(false);
mLoadingThumbnail.eraseColor(0xFFffffff);
mDefaultApplicationIcon = new BitmapDrawable(context.getResources(), icon);
// Initialize the proxy, cache and loaders
@@ -500,17 +497,16 @@ public class RecentsTaskLoader {
// use the default assets in their place until they load
boolean requiresLoad = (applicationIcon == null) || (thumbnail == null);
applicationIcon = applicationIcon != null ? applicationIcon : mDefaultApplicationIcon;
thumbnail = thumbnail != null ? thumbnail : mDefaultThumbnail;
if (requiresLoad) {
mLoadQueue.addTask(t);
}
t.notifyTaskDataLoaded(thumbnail, applicationIcon);
t.notifyTaskDataLoaded(thumbnail == mDefaultThumbnail ? null : thumbnail, applicationIcon);
}
/** Releases the task resource data back into the pool. */
public void unloadTaskData(Task t) {
mLoadQueue.removeTask(t);
t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
t.notifyTaskDataUnloaded(null, mDefaultApplicationIcon);
}
/** Completely removes the resource data from the pool. */
@@ -519,7 +515,7 @@ public class RecentsTaskLoader {
mThumbnailCache.remove(t.key);
mApplicationIconCache.remove(t.key);
if (notifyTaskDataUnloaded) {
t.notifyTaskDataUnloaded(mDefaultThumbnail, mDefaultApplicationIcon);
t.notifyTaskDataUnloaded(null, mDefaultApplicationIcon);
}
}

View File

@@ -44,7 +44,6 @@ public class AnimateableViewBounds extends ViewOutlineProvider {
mConfig = RecentsConfiguration.getInstance();
mSourceView = source;
mCornerRadius = cornerRadius;
mSourceView.setClipToOutline(true);
setClipTop(getClipTop());
setClipRight(getClipRight());
setClipBottom(getClipBottom());

View File

@@ -637,17 +637,31 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Returns the current dim. */
public void setDim(int dim) {
mDim = dim;
// 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();
}
if (mDimAnimator != null) {
mDimAnimator.removeAllListeners();
mDimAnimator.cancel();
}
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);
setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
int inverse = 255 - mDim;
mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
mLayerPaint.setColorFilter(mDimColorFilter);
setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
}
} else {
float dimAlpha = mDim / 255.0f;
if (mThumbnailView != null) {
mThumbnailView.setDimAlpha(dimAlpha);
}
if (mHeaderView != null) {
mHeaderView.setDimAlpha(dim);
}
}
}

View File

@@ -30,10 +30,13 @@ import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
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;
@@ -58,17 +61,20 @@ public class TaskViewHeader extends FrameLayout {
TextView mActivityDescription;
RippleDrawable mBackground;
ColorDrawable mBackgroundColor;
GradientDrawable mBackgroundColorDrawable;
int mBackgroundColor;
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
AnimatorSet mFocusAnimator;
ValueAnimator backgroundColorAnimator;
PorterDuffColorFilter mDimFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
boolean mIsFullscreen;
boolean mCurrentPrimaryColorIsDark;
int mCurrentPrimaryColor;
static Paint sHighlightPaint;
private Paint mDimPaint = new Paint();
public TaskViewHeader(Context context) {
this(context, null);
@@ -140,13 +146,14 @@ public class TaskViewHeader extends FrameLayout {
}
}
mBackgroundColor = new ColorDrawable(0);
mBackgroundColorDrawable = (GradientDrawable) getContext().getDrawable(R.drawable
.recents_task_view_header_bg_color);
// Copy the ripple drawable since we are going to be manipulating it
mBackground = (RippleDrawable)
getContext().getDrawable(R.drawable.recents_task_view_header_bg);
mBackground = (RippleDrawable) mBackground.mutate().getConstantState().newDrawable();
mBackground.setColor(ColorStateList.valueOf(0));
mBackground.setDrawableByLayerId(mBackground.getId(0), mBackgroundColor);
mBackground.setDrawableByLayerId(mBackground.getId(0), mBackgroundColorDrawable);
setBackground(mBackground);
}
@@ -197,7 +204,8 @@ public class TaskViewHeader extends FrameLayout {
int existingBgColor = (getBackground() instanceof ColorDrawable) ?
((ColorDrawable) getBackground()).getColor() : 0;
if (existingBgColor != t.colorPrimary) {
mBackgroundColor.setColor(t.colorPrimary);
mBackgroundColorDrawable.setColor(t.colorPrimary);
mBackgroundColor = t.colorPrimary;
}
mCurrentPrimaryColor = t.colorPrimary;
mCurrentPrimaryColorIsDark = t.useLightOnPrimaryColor;
@@ -276,7 +284,7 @@ public class TaskViewHeader extends FrameLayout {
mBackground.setColor(new ColorStateList(states, colors));
mBackground.setState(newStates);
// Pulse the background color
int currentColor = mBackgroundColor.getColor();
int currentColor = mBackgroundColor;
int lightPrimaryColor = getSecondaryColor(mCurrentPrimaryColor, mCurrentPrimaryColorIsDark);
ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
lightPrimaryColor, currentColor);
@@ -289,7 +297,9 @@ public class TaskViewHeader extends FrameLayout {
backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mBackgroundColor.setColor((Integer) animation.getAnimatedValue());
int color = (int) animation.getAnimatedValue();
mBackgroundColorDrawable.setColor(color);
mBackgroundColor = color;
}
});
backgroundColor.setRepeatCount(ValueAnimator.INFINITE);
@@ -307,13 +317,15 @@ public class TaskViewHeader extends FrameLayout {
} else {
if (isRunning) {
// Restore the background color
int currentColor = mBackgroundColor.getColor();
int currentColor = mBackgroundColor;
ValueAnimator backgroundColor = ValueAnimator.ofObject(new ArgbEvaluator(),
currentColor, mCurrentPrimaryColor);
backgroundColor.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mBackgroundColor.setColor((Integer) animation.getAnimatedValue());
int color = (int) animation.getAnimatedValue();
mBackgroundColorDrawable.setColor(color);
mBackgroundColor = color;
}
});
// Restore the translation
@@ -329,4 +341,11 @@ 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

@@ -16,9 +16,20 @@
package com.android.systemui.recents.views;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LightingColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import com.android.systemui.recents.RecentsConfiguration;
@@ -26,12 +37,30 @@ import com.android.systemui.recents.model.Task;
/** The task thumbnail view */
public class TaskViewThumbnail extends FixedSizeImageView {
public class TaskViewThumbnail extends View {
private final int mCornerRadius;
private final Matrix mScaleMatrix = new Matrix();
RecentsConfiguration mConfig;
// Task bar clipping
Rect mClipRect = new Rect();
Paint mDrawPaint = new Paint();
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 ValueAnimator mAlphaAnimator;
private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener
= new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mBitmapAlpha = (float) animation.getAnimatedValue();
updateFilter();
}
};
public TaskViewThumbnail(Context context) {
this(context, null);
@@ -48,12 +77,43 @@ public class TaskViewThumbnail extends FixedSizeImageView {
public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mConfig = RecentsConfiguration.getInstance();
setScaleType(ScaleType.FIT_XY);
mCornerRadius = mConfig.taskViewRoundedCornerRadiusPx;
mDrawPaint.setColorFilter(mLightingColorFilter);
mDrawPaint.setFilterBitmap(true);
mDrawPaint.setAntiAlias(true);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawRoundRect(0,
0,
getWidth(),
getHeight(),
mCornerRadius,
mCornerRadius,
mDrawPaint);
}
@Override
protected void onFinishInflate() {
setAlpha(0.9f);
mBitmapAlpha = 0.9f;
updateFilter();
}
private void updateFilter() {
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. */
@@ -72,11 +132,8 @@ public class TaskViewThumbnail extends FixedSizeImageView {
/** Binds the thumbnail view to the screenshot. */
boolean bindToScreenshot(Bitmap ss) {
if (ss != null) {
setImageBitmap(ss);
return true;
}
return false;
setImageBitmap(ss);
return ss != null;
}
/** Unbinds the thumbnail view from the screenshot. */
@@ -88,12 +145,49 @@ public class TaskViewThumbnail extends FixedSizeImageView {
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();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (changed) {
mLayoutRect.set(0, 0, getWidth(), getHeight());
updateBitmapScale();
}
}
private void updateBitmapScale() {
if (mBitmapShader != null) {
mScaleMatrix.setRectToRect(mBitmapRect, mLayoutRect, Matrix.ScaleToFit.FILL);
mBitmapShader.setLocalMatrix(mScaleMatrix);
}
}
public void setDimAlpha(float dimAlpha) {
mDimAlpha = dimAlpha;
updateFilter();
}
/** Unbinds the thumbnail view from the task */
void unbindFromTask() {
setImageDrawable(null);
setImageBitmap(null);
}
/** Handles focus changes. */
@@ -112,10 +206,11 @@ public class TaskViewThumbnail extends FixedSizeImageView {
/** Prepares for the enter recents animation. */
void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask) {
if (isTaskViewLaunchTargetTask) {
setAlpha(1f);
mBitmapAlpha = 1f;
} else {
setAlpha(mConfig.taskViewThumbnailAlpha);
mBitmapAlpha = mConfig.taskViewThumbnailAlpha;
}
updateFilter();
}
/** Animates this task thumbnail as it enters recents */
@@ -130,16 +225,32 @@ public class TaskViewThumbnail extends FixedSizeImageView {
}
/** Animates the thumbnail alpha. */
void startFadeAnimation(float finalAlpha, int delay, int duration, Runnable postAnimRunnable) {
if (postAnimRunnable != null) {
animate().withEndAction(postAnimRunnable);
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();
if (postAnimRunnable != null) {
mAlphaAnimator.addListener(new AnimatorListenerAdapter() {
public boolean mCancelled;
@Override
public void onAnimationCancel(Animator animation) {
mCancelled = true;
}
@Override
public void onAnimationEnd(Animator animation) {
if (!mCancelled) {
postAnimRunnable.run();
}
}
});
}
animate()
.alpha(finalAlpha)
.setStartDelay(delay)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(duration)
.withLayer()
.start();
}
}