2 * Copyright (C) 2014 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.systemui.recents.views;
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.graphics.Canvas;
22 import android.graphics.Paint;
23 import android.graphics.PorterDuff;
24 import android.graphics.PorterDuffXfermode;
25 import android.graphics.drawable.ColorDrawable;
26 import android.graphics.drawable.Drawable;
27 import android.graphics.drawable.RippleDrawable;
28 import android.util.AttributeSet;
29 import android.view.MotionEvent;
30 import android.view.View;
31 import android.widget.FrameLayout;
32 import android.widget.ImageView;
33 import android.widget.TextView;
34 import com.android.systemui.R;
35 import com.android.systemui.recents.Constants;
36 import com.android.systemui.recents.RecentsConfiguration;
37 import com.android.systemui.recents.model.Task;
40 /* The task bar view */
41 class TaskViewHeader extends FrameLayout {
43 RecentsConfiguration mConfig;
45 ImageView mDismissButton;
46 ImageView mApplicationIcon;
47 TextView mActivityDescription;
49 Drawable mLightDismissDrawable;
50 Drawable mDarkDismissDrawable;
52 boolean mIsFullscreen;
54 static Paint sHighlightPaint;
56 public TaskViewHeader(Context context) {
60 public TaskViewHeader(Context context, AttributeSet attrs) {
61 this(context, attrs, 0);
64 public TaskViewHeader(Context context, AttributeSet attrs, int defStyleAttr) {
65 this(context, attrs, defStyleAttr, 0);
68 public TaskViewHeader(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
69 super(context, attrs, defStyleAttr, defStyleRes);
70 mConfig = RecentsConfiguration.getInstance();
71 setWillNotDraw(false);
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);
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);
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;
94 return super.onTouchEvent(event);
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);
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);
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);
123 /** Sets whether the current task is full screen or not. */
124 void setIsFullscreen(boolean isFullscreen) {
125 mIsFullscreen = isFullscreen;
129 public boolean hasOverlappingRendering() {
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);
142 mApplicationIcon.setContentDescription(t.activityLabel);
143 if (!mActivityDescription.getText().toString().equals(t.activityLabel)) {
144 mActivityDescription.setText(t.activityLabel);
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);
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,
161 /** Unbinds the bar view from the task */
162 void unbindFromTask() {
163 mApplicationIcon.setImageDrawable(null);
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);
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());
179 .setStartDelay(delay)
180 .setInterpolator(mConfig.fastOutSlowInInterpolator)
181 .setDuration(mConfig.taskBarEnterAnimDuration)
182 .withEndAction(postAnimRunnable)
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
190 .translationY(-getMeasuredHeight())
192 .setInterpolator(mConfig.fastOutLinearInInterpolator)
193 .setDuration(mConfig.taskBarExitAnimDuration)
194 .withStartAction(preAnimRunnable)
195 .withEndAction(new Runnable() {
198 post(postAnimRunnable);
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()
211 .setInterpolator(mConfig.fastOutSlowInInterpolator)
212 .setDuration(mConfig.taskBarExitAnimDuration)
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()
225 .setInterpolator(mConfig.fastOutLinearInInterpolator)
226 .setDuration(mConfig.taskBarEnterAnimDuration)
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);