TaskViewThumbnail.java revision e8199c582d826a39e6e47b0d8418834c15242fec
1/* 2 * Copyright (C) 2014 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.systemui.recents.views; 18 19import android.animation.Animator; 20import android.animation.AnimatorListenerAdapter; 21import android.animation.ValueAnimator; 22import android.content.Context; 23import android.graphics.Bitmap; 24import android.graphics.BitmapShader; 25import android.graphics.Canvas; 26import android.graphics.Color; 27import android.graphics.LightingColorFilter; 28import android.graphics.Matrix; 29import android.graphics.Paint; 30import android.graphics.Rect; 31import android.graphics.RectF; 32import android.graphics.Shader; 33import android.util.AttributeSet; 34import android.view.View; 35import com.android.systemui.recents.RecentsConfiguration; 36import com.android.systemui.recents.model.Task; 37 38 39/** The task thumbnail view */ 40public class TaskViewThumbnail extends View { 41 42 private final int mCornerRadius; 43 private final Matrix mScaleMatrix = new Matrix(); 44 RecentsConfiguration mConfig; 45 46 // Task bar clipping 47 Rect mClipRect = new Rect(); 48 Paint mDrawPaint = new Paint(); 49 LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0); 50 private final RectF mBitmapRect = new RectF(); 51 private final RectF mLayoutRect = new RectF(); 52 private BitmapShader mBitmapShader; 53 private float mBitmapAlpha; 54 private float mDimAlpha; 55 private ValueAnimator mAlphaAnimator; 56 private ValueAnimator.AnimatorUpdateListener mAlphaUpdateListener 57 = new ValueAnimator.AnimatorUpdateListener() { 58 @Override 59 public void onAnimationUpdate(ValueAnimator animation) { 60 mBitmapAlpha = (float) animation.getAnimatedValue(); 61 updateFilter(); 62 } 63 }; 64 65 public TaskViewThumbnail(Context context) { 66 this(context, null); 67 } 68 69 public TaskViewThumbnail(Context context, AttributeSet attrs) { 70 this(context, attrs, 0); 71 } 72 73 public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr) { 74 this(context, attrs, defStyleAttr, 0); 75 } 76 77 public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 78 super(context, attrs, defStyleAttr, defStyleRes); 79 mConfig = RecentsConfiguration.getInstance(); 80 mCornerRadius = mConfig.taskViewRoundedCornerRadiusPx; 81 mDrawPaint.setColorFilter(mLightingColorFilter); 82 mDrawPaint.setFilterBitmap(true); 83 mDrawPaint.setAntiAlias(true); 84 } 85 86 @Override 87 protected void onDraw(Canvas canvas) { 88 canvas.drawRoundRect(0, 89 0, 90 getWidth(), 91 getHeight(), 92 mCornerRadius, 93 mCornerRadius, 94 mDrawPaint); 95 } 96 97 @Override 98 protected void onFinishInflate() { 99 mBitmapAlpha = 0.9f; 100 updateFilter(); 101 } 102 103 private void updateFilter() { 104 int mul = (int) ((1.0f - mDimAlpha) * mBitmapAlpha * 255); 105 int add = (int) ((1.0f - mDimAlpha) * (1 - mBitmapAlpha) * 255); 106 if (mBitmapShader != null) { 107 mLightingColorFilter.setColorMultiply(Color.argb(255, mul, mul, mul)); 108 mLightingColorFilter.setColorAdd(Color.argb(0, add, add, add)); 109 mDrawPaint.setColorFilter(mLightingColorFilter); 110 mDrawPaint.setColor(0xffffffff); 111 } else { 112 mDrawPaint.setColorFilter(null); 113 int grey = mul + add; 114 mDrawPaint.setColor(Color.argb(255, grey, grey, grey)); 115 } 116 invalidate(); 117 } 118 119 /** Updates the clip rect based on the given task bar. */ 120 void enableTaskBarClip(View taskBar) { 121 int top = (int) Math.max(0, taskBar.getTranslationY() + 122 taskBar.getMeasuredHeight() - 1); 123 mClipRect.set(0, top, getMeasuredWidth(), getMeasuredHeight()); 124 setClipBounds(mClipRect); 125 } 126 127 /** Disables the task bar clipping. */ 128 void disableTaskBarClip() { 129 mClipRect.set(0, 0, getMeasuredWidth(), getMeasuredHeight()); 130 setClipBounds(mClipRect); 131 } 132 133 /** Binds the thumbnail view to the screenshot. */ 134 boolean bindToScreenshot(Bitmap ss) { 135 setImageBitmap(ss); 136 return ss != null; 137 } 138 139 /** Unbinds the thumbnail view from the screenshot. */ 140 void unbindFromScreenshot() { 141 setImageBitmap(null); 142 } 143 144 /** Binds the thumbnail view to the task */ 145 void rebindToTask(Task t) { 146 if (t.thumbnail != null) { 147 setImageBitmap(t.thumbnail); 148 } else { 149 setImageBitmap(null); 150 } 151 } 152 153 public void setImageBitmap(Bitmap bm) { 154 if (bm != null) { 155 mBitmapShader = new BitmapShader(bm, Shader.TileMode.CLAMP, 156 Shader.TileMode.CLAMP); 157 mDrawPaint.setShader(mBitmapShader); 158 mBitmapRect.set(0, 0, bm.getWidth(), bm.getHeight()); 159 updateBitmapScale(); 160 } else { 161 mBitmapShader = null; 162 mDrawPaint.setShader(null); 163 } 164 updateFilter(); 165 } 166 167 @Override 168 protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 169 super.onLayout(changed, left, top, right, bottom); 170 if (changed) { 171 mLayoutRect.set(0, 0, getWidth(), getHeight()); 172 updateBitmapScale(); 173 } 174 } 175 176 private void updateBitmapScale() { 177 if (mBitmapShader != null) { 178 mScaleMatrix.setRectToRect(mBitmapRect, mLayoutRect, Matrix.ScaleToFit.FILL); 179 mBitmapShader.setLocalMatrix(mScaleMatrix); 180 } 181 } 182 183 public void setDimAlpha(float dimAlpha) { 184 mDimAlpha = dimAlpha; 185 updateFilter(); 186 } 187 188 /** Unbinds the thumbnail view from the task */ 189 void unbindFromTask() { 190 setImageBitmap(null); 191 } 192 193 /** Handles focus changes. */ 194 void onFocusChanged(boolean focused) { 195 if (focused) { 196 if (Float.compare(getAlpha(), 1f) != 0) { 197 startFadeAnimation(1f, 0, 150, null); 198 } 199 } else { 200 if (Float.compare(getAlpha(), mConfig.taskViewThumbnailAlpha) != 0) { 201 startFadeAnimation(mConfig.taskViewThumbnailAlpha, 0, 150, null); 202 } 203 } 204 } 205 206 /** Prepares for the enter recents animation. */ 207 void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask) { 208 if (isTaskViewLaunchTargetTask) { 209 mBitmapAlpha = 1f; 210 } else { 211 mBitmapAlpha = mConfig.taskViewThumbnailAlpha; 212 } 213 updateFilter(); 214 } 215 216 /** Animates this task thumbnail as it enters recents */ 217 void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) { 218 startFadeAnimation(mConfig.taskViewThumbnailAlpha, delay, 219 mConfig.taskBarEnterAnimDuration, postAnimRunnable); 220 } 221 222 /** Animates this task thumbnail as it exits recents */ 223 void startLaunchTaskAnimation(Runnable postAnimRunnable) { 224 startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, postAnimRunnable); 225 } 226 227 /** Animates the thumbnail alpha. */ 228 void startFadeAnimation(float finalAlpha, int delay, int duration, final Runnable postAnimRunnable) { 229 if (mAlphaAnimator != null) { 230 mAlphaAnimator.cancel(); 231 } 232 mAlphaAnimator = ValueAnimator.ofFloat(mBitmapAlpha, finalAlpha); 233 mAlphaAnimator.addUpdateListener(mAlphaUpdateListener); 234 mAlphaAnimator.setStartDelay(delay); 235 mAlphaAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator); 236 mAlphaAnimator.setDuration(duration); 237 mAlphaAnimator.start(); 238 if (postAnimRunnable != null) { 239 mAlphaAnimator.addListener(new AnimatorListenerAdapter() { 240 public boolean mCancelled; 241 242 @Override 243 public void onAnimationCancel(Animator animation) { 244 mCancelled = true; 245 } 246 247 @Override 248 public void onAnimationEnd(Animator animation) { 249 if (!mCancelled) { 250 postAnimRunnable.run(); 251 } 252 } 253 }); 254 } 255 } 256} 257