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