TaskViewHeader.java revision ec396d6399c5c31d697d81e94aff459e9771b0c6
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.content.res.Resources;
21import android.graphics.Canvas;
22import android.graphics.Paint;
23import android.graphics.PorterDuff;
24import android.graphics.PorterDuffXfermode;
25import android.graphics.drawable.ColorDrawable;
26import android.graphics.drawable.Drawable;
27import android.graphics.drawable.RippleDrawable;
28import android.util.AttributeSet;
29import android.view.MotionEvent;
30import android.view.View;
31import android.widget.FrameLayout;
32import android.widget.ImageView;
33import android.widget.TextView;
34import com.android.systemui.R;
35import com.android.systemui.recents.Constants;
36import com.android.systemui.recents.RecentsConfiguration;
37import com.android.systemui.recents.model.Task;
38
39
40/* The task bar view */
41class TaskViewHeader extends FrameLayout {
42
43    RecentsConfiguration mConfig;
44
45    ImageView mDismissButton;
46    ImageView mApplicationIcon;
47    TextView mActivityDescription;
48
49    Drawable mLightDismissDrawable;
50    Drawable mDarkDismissDrawable;
51
52    boolean mIsFullscreen;
53
54    static Paint sHighlightPaint;
55
56    public TaskViewHeader(Context context) {
57        this(context, null);
58    }
59
60    public TaskViewHeader(Context context, AttributeSet attrs) {
61        this(context, attrs, 0);
62    }
63
64    public TaskViewHeader(Context context, AttributeSet attrs, int defStyleAttr) {
65        this(context, attrs, defStyleAttr, 0);
66    }
67
68    public TaskViewHeader(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
69        super(context, attrs, defStyleAttr, defStyleRes);
70        mConfig = RecentsConfiguration.getInstance();
71        setWillNotDraw(false);
72
73        // Load the dismiss resources
74        Resources res = context.getResources();
75        mLightDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_light);
76        mDarkDismissDrawable = res.getDrawable(R.drawable.recents_dismiss_dark);
77
78        // Configure the highlight paint
79        if (sHighlightPaint == null) {
80            sHighlightPaint = new Paint();
81            sHighlightPaint.setStyle(Paint.Style.STROKE);
82            sHighlightPaint.setStrokeWidth(mConfig.taskViewHighlightPx);
83            sHighlightPaint.setColor(mConfig.taskBarViewHighlightColor);
84            sHighlightPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
85            sHighlightPaint.setAntiAlias(true);
86        }
87    }
88
89    @Override
90    public boolean onTouchEvent(MotionEvent event) {
91        // We ignore taps on the task bar except on the filter and dismiss buttons
92        if (!Constants.DebugFlags.App.EnableTaskBarTouchEvents) return true;
93
94        return super.onTouchEvent(event);
95    }
96
97    @Override
98    protected void onFinishInflate() {
99        // Initialize the icon and description views
100        mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
101        mActivityDescription = (TextView) findViewById(R.id.activity_description);
102        mDismissButton = (ImageView) findViewById(R.id.dismiss_task);
103
104        // Hide the backgrounds if they are ripple drawables
105        if (!Constants.DebugFlags.App.EnableTaskFiltering) {
106            if (mApplicationIcon.getBackground() instanceof RippleDrawable) {
107                mApplicationIcon.setBackground(null);
108            }
109        }
110    }
111
112    @Override
113    protected void onDraw(Canvas canvas) {
114        if (!mIsFullscreen) {
115            // Draw the highlight at the top edge (but put the bottom edge just out of view)
116            float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f);
117            float radius = mConfig.taskViewRoundedCornerRadiusPx;
118            canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
119                    getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
120        }
121    }
122
123    /** Sets whether the current task is full screen or not. */
124    void setIsFullscreen(boolean isFullscreen) {
125        mIsFullscreen = isFullscreen;
126    }
127
128    @Override
129    public boolean hasOverlappingRendering() {
130        return false;
131    }
132
133    /** Binds the bar view to the task */
134    void rebindToTask(Task t) {
135        // If an activity icon is defined, then we use that as the primary icon to show in the bar,
136        // otherwise, we fall back to the application icon
137        if (t.activityIcon != null) {
138            mApplicationIcon.setImageDrawable(t.activityIcon);
139        } else if (t.applicationIcon != null) {
140            mApplicationIcon.setImageDrawable(t.applicationIcon);
141        }
142        mApplicationIcon.setContentDescription(t.activityLabel);
143        if (!mActivityDescription.getText().toString().equals(t.activityLabel)) {
144            mActivityDescription.setText(t.activityLabel);
145        }
146        // Try and apply the system ui tint
147        int existingBgColor = (getBackground() instanceof ColorDrawable) ?
148                ((ColorDrawable) getBackground()).getColor() : 0;
149        if (existingBgColor != t.colorPrimary) {
150            setBackgroundColor(t.colorPrimary);
151        }
152        mActivityDescription.setTextColor(t.useLightOnPrimaryColor ?
153                mConfig.taskBarViewLightTextColor : mConfig.taskBarViewDarkTextColor);
154        mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
155                mLightDismissDrawable : mDarkDismissDrawable);
156        mDismissButton.setContentDescription(
157                getContext().getString(R.string.accessibility_recents_item_will_be_dismissed,
158                        t.activityLabel));
159    }
160
161    /** Unbinds the bar view from the task */
162    void unbindFromTask() {
163        mApplicationIcon.setImageDrawable(null);
164    }
165
166    /** Prepares this task view for the enter-recents animations.  This is called earlier in the
167     * first layout because the actual animation into recents may take a long time. */
168    public void prepareEnterRecentsAnimation() {
169        setVisibility(View.INVISIBLE);
170    }
171
172    /** Animates this task bar as it enters recents */
173    public void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
174        // Animate the task bar of the first task view
175        setVisibility(View.VISIBLE);
176        setTranslationY(-getMeasuredHeight());
177        animate()
178                .translationY(0)
179                .setStartDelay(delay)
180                .setInterpolator(mConfig.fastOutSlowInInterpolator)
181                .setDuration(mConfig.taskBarEnterAnimDuration)
182                .withEndAction(postAnimRunnable)
183                .start();
184    }
185
186    /** Animates this task bar as it exits recents */
187    public void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable) {
188        // Animate the task bar out of the first task view
189        animate()
190                .translationY(-getMeasuredHeight())
191                .setStartDelay(0)
192                .setInterpolator(mConfig.fastOutLinearInInterpolator)
193                .setDuration(mConfig.taskBarExitAnimDuration)
194                .withStartAction(preAnimRunnable)
195                .withEndAction(new Runnable() {
196                    @Override
197                    public void run() {
198                        post(postAnimRunnable);
199                    }
200                })
201                .start();
202    }
203
204    /** Animates this task bar dismiss button when launching a task. */
205    public void startLaunchTaskDismissAnimation() {
206        if (mDismissButton.getVisibility() == View.VISIBLE) {
207            mDismissButton.animate().cancel();
208            mDismissButton.animate()
209                    .alpha(0f)
210                    .setStartDelay(0)
211                    .setInterpolator(mConfig.fastOutSlowInInterpolator)
212                    .setDuration(mConfig.taskBarExitAnimDuration)
213                    .withLayer()
214                    .start();
215        }
216    }
217
218    /** Animates this task bar if the user does not interact with the stack after a certain time. */
219    public void startNoUserInteractionAnimation() {
220        mDismissButton.setVisibility(View.VISIBLE);
221        mDismissButton.setAlpha(0f);
222        mDismissButton.animate()
223                .alpha(1f)
224                .setStartDelay(0)
225                .setInterpolator(mConfig.fastOutLinearInInterpolator)
226                .setDuration(mConfig.taskBarEnterAnimDuration)
227                .withLayer()
228                .start();
229    }
230
231    /** Mark this task view that the user does has not interacted with the stack after a certain time. */
232    public void setNoUserInteractionState() {
233        if (mDismissButton.getVisibility() != View.VISIBLE) {
234            mDismissButton.animate().cancel();
235            mDismissButton.setVisibility(View.VISIBLE);
236            mDismissButton.setAlpha(1f);
237        }
238    }
239}
240