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