TaskView.java revision 37c8d8ef855aacb074ee0b702a46dbc62b7551a2
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.content.Context;
20import android.graphics.Canvas;
21import android.graphics.Path;
22import android.graphics.Rect;
23import android.graphics.RectF;
24import android.util.AttributeSet;
25import android.view.View;
26import android.view.animation.AccelerateDecelerateInterpolator;
27import android.view.animation.DecelerateInterpolator;
28import android.widget.FrameLayout;
29import com.android.systemui.R;
30import com.android.systemui.recents.Constants;
31import com.android.systemui.recents.RecentsConfiguration;
32import com.android.systemui.recents.model.Task;
33
34
35/* A task view */
36public class TaskView extends FrameLayout implements View.OnClickListener, Task.TaskCallbacks {
37    /** The TaskView callbacks */
38    interface TaskViewCallbacks {
39        public void onTaskIconClicked(TaskView tv);
40        // public void onTaskViewReboundToTask(TaskView tv, Task t);
41    }
42
43    Task mTask;
44    boolean mTaskDataLoaded;
45
46    TaskThumbnailView mThumbnailView;
47    TaskBarView mBarView;
48    TaskViewCallbacks mCb;
49
50    Path mRoundedRectClipPath = new Path();
51
52
53    public TaskView(Context context) {
54        this(context, null);
55    }
56
57    public TaskView(Context context, AttributeSet attrs) {
58        this(context, attrs, 0);
59    }
60
61    public TaskView(Context context, AttributeSet attrs, int defStyleAttr) {
62        this(context, attrs, defStyleAttr, 0);
63    }
64
65    public TaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
66        super(context, attrs, defStyleAttr, defStyleRes);
67        setWillNotDraw(false);
68    }
69
70    @Override
71    protected void onFinishInflate() {
72        // Bind the views
73        mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
74        mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
75        if (mTaskDataLoaded) {
76            onTaskDataLoaded(false);
77        }
78    }
79
80    @Override
81    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
82        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
83
84        // Update the rounded rect clip path
85        RecentsConfiguration config = RecentsConfiguration.getInstance();
86        float radius = config.pxFromDp(Constants.Values.TaskView.RoundedCornerRadiusDps);
87        mRoundedRectClipPath.reset();
88        mRoundedRectClipPath.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()),
89                radius, radius, Path.Direction.CW);
90    }
91
92    @Override
93    protected void onDraw(Canvas canvas) {
94        if (Constants.Values.TaskView.UseRoundedCorners) {
95            canvas.clipPath(mRoundedRectClipPath);
96        }
97
98        super.onDraw(canvas);
99    }
100
101    /** Set callback */
102    void setCallbacks(TaskViewCallbacks cb) {
103        mCb = cb;
104    }
105
106    /** Gets the task */
107    Task getTask() {
108        return mTask;
109    }
110
111    /** Synchronizes this view's properties with the task's transform */
112    void updateViewPropertiesFromTask(TaskViewTransform animateFromTransform,
113                                      TaskViewTransform transform, int duration) {
114        if (duration > 0) {
115            if (animateFromTransform != null) {
116                setTranslationY(animateFromTransform.translationY);
117                setScaleX(animateFromTransform.scale);
118                setScaleY(animateFromTransform.scale);
119            }
120            animate().translationY(transform.translationY)
121                    .scaleX(transform.scale)
122                    .scaleY(transform.scale)
123                    .setDuration(duration)
124                    .setInterpolator(new AccelerateDecelerateInterpolator())
125                    .start();
126        } else {
127            setTranslationY(transform.translationY);
128            setScaleX(transform.scale);
129            setScaleY(transform.scale);
130        }
131    }
132
133    /** Resets this view's properties */
134    void resetViewProperties() {
135        setTranslationX(0f);
136        setTranslationY(0f);
137        setScaleX(1f);
138        setScaleY(1f);
139        setAlpha(1f);
140    }
141
142    /** Animates this task view as it enters recents */
143    public void animateOnEnterRecents() {
144        RecentsConfiguration config = RecentsConfiguration.getInstance();
145        int translate = config.pxFromDp(10);
146        mBarView.setScaleX(1.25f);
147        mBarView.setScaleY(1.25f);
148        mBarView.setAlpha(0f);
149        mBarView.setTranslationX(translate / 2);
150        mBarView.setTranslationY(-translate);
151        mBarView.animate()
152                .alpha(1f)
153                .scaleX(1f)
154                .scaleY(1f)
155                .translationX(0)
156                .translationY(0)
157                .setStartDelay(235)
158                .setDuration(Constants.Values.TaskView.Animation.TaskIconOnEnterDuration)
159                .withLayer()
160                .start();
161    }
162
163    /** Animates this task view as it exits recents */
164    public void animateOnLeavingRecents(final Runnable r) {
165        RecentsConfiguration config = RecentsConfiguration.getInstance();
166        int translate = config.pxFromDp(10);
167        mBarView.animate()
168            .alpha(0f)
169            .scaleX(1.1f)
170            .scaleY(1.1f)
171            .translationX(translate / 2)
172            .translationY(-translate)
173            .setStartDelay(0)
174            .setDuration(Constants.Values.TaskView.Animation.TaskIconOnLeavingDuration)
175            .setInterpolator(new DecelerateInterpolator())
176            .withLayer()
177            .withEndAction(r)
178            .start();
179    }
180
181    /** Returns the rect we want to clip (it may not be the full rect) */
182    Rect getClippingRect(Rect outRect, boolean accountForRoundedRects) {
183        getHitRect(outRect);
184        // XXX: We should get the hit rect of the thumbnail view and intersect, but this is faster
185        outRect.right = outRect.left + mThumbnailView.getRight();
186        outRect.bottom = outRect.top + mThumbnailView.getBottom();
187        // We need to shrink the next rect by the rounded corners since those are draw on
188        // top of the current view
189        if (accountForRoundedRects) {
190            RecentsConfiguration config = RecentsConfiguration.getInstance();
191            float radius = config.pxFromDp(Constants.Values.TaskView.RoundedCornerRadiusDps);
192            outRect.inset((int) radius, (int) radius);
193        }
194        return outRect;
195    }
196
197    /** Enable the hw layers on this task view */
198    void enableHwLayers() {
199        mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
200    }
201
202    /** Disable the hw layers on this task view */
203    void disableHwLayers() {
204        mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, null);
205    }
206
207    /**** TaskCallbacks Implementation ****/
208
209    /** Binds this task view to the task */
210    public void onTaskBound(Task t) {
211        mTask = t;
212        mTask.setCallbacks(this);
213    }
214
215    @Override
216    public void onTaskDataLoaded(boolean reloadingTaskData) {
217        if (mThumbnailView != null && mBarView != null) {
218            // Bind each of the views to the new task data
219            mThumbnailView.rebindToTask(mTask, reloadingTaskData);
220            mBarView.rebindToTask(mTask, reloadingTaskData);
221        }
222        mTaskDataLoaded = true;
223    }
224
225    @Override
226    public void onTaskDataUnloaded() {
227        if (mThumbnailView != null && mBarView != null) {
228            // Unbind each of the views from the task data and remove the task callback
229            mTask.setCallbacks(null);
230            mThumbnailView.unbindFromTask();
231            mBarView.unbindFromTask();
232        }
233        mTaskDataLoaded = false;
234    }
235
236    @Override
237    public void onClick(View v) {
238        mCb.onTaskIconClicked(this);
239    }
240}