blob: 28880dfd0e2745ff2b611b204b9ff338d3320471 [file] [log] [blame]
Winson Chung303e1ff2014-03-07 15:06:19 -08001/*
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
Winson231bc9c2016-02-09 12:31:00 -080019import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
20
Winsonf24f2162016-01-05 12:11:55 -080021import android.animation.Animator;
22import android.animation.AnimatorListenerAdapter;
Winson49df4202016-01-25 17:33:34 -080023import android.animation.ObjectAnimator;
Jorim Jaggi192086e2016-03-11 17:17:03 +010024import android.app.ActivityOptions.OnAnimationStartedListener;
Winson Chung303e1ff2014-03-07 15:06:19 -080025import android.content.Context;
Winson Chung303e1ff2014-03-07 15:06:19 -080026import android.graphics.Canvas;
Winson49df4202016-01-25 17:33:34 -080027import android.graphics.Color;
28import android.graphics.Outline;
Winson Chung303e1ff2014-03-07 15:06:19 -080029import android.graphics.Rect;
Winson49df4202016-01-25 17:33:34 -080030import android.graphics.drawable.ColorDrawable;
Winson4165d3362015-10-10 14:40:35 -070031import android.graphics.drawable.Drawable;
Jorim Jaggic69bd222016-03-15 14:38:37 +010032import android.os.Bundle;
Winson83c1b072015-11-09 10:48:04 -080033import android.os.Handler;
Jorim Jaggic69bd222016-03-15 14:38:37 +010034import android.os.IRemoteCallback;
35import android.os.RemoteException;
Winson882072b2015-10-12 11:26:33 -070036import android.util.ArraySet;
Winson Chung8e548f72014-06-24 14:40:53 -070037import android.util.AttributeSet;
Jorim Jaggic69bd222016-03-15 14:38:37 +010038import android.view.AppTransitionAnimationSpec;
39import android.view.IAppTransitionAnimationSpecsFuture;
Winson Chungecd9b302014-04-16 17:07:18 -070040import android.view.LayoutInflater;
Winsonbe7607a2015-10-01 17:24:51 -070041import android.view.MotionEvent;
Winsonc29ff002015-11-20 16:00:45 -080042import android.view.View;
Winson231bc9c2016-02-09 12:31:00 -080043import android.view.ViewDebug;
Winson49df4202016-01-25 17:33:34 -080044import android.view.ViewOutlineProvider;
Jorim Jaggi870ab5a2015-12-02 18:37:54 -080045import android.view.ViewPropertyAnimator;
Winson Chung653f70c22014-05-19 14:49:42 -070046import android.view.WindowInsets;
Jorim Jaggic69bd222016-03-15 14:38:37 +010047import android.view.WindowManagerGlobal;
Winson Chung303e1ff2014-03-07 15:06:19 -080048import android.widget.FrameLayout;
Winson Chungde750de2015-12-11 10:26:06 -050049import android.widget.TextView;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050050
Jorim Jaggic69bd222016-03-15 14:38:37 +010051import com.android.internal.annotations.GuardedBy;
Winsondc8de842016-01-06 15:21:41 -080052import com.android.internal.logging.MetricsLogger;
Chris Wrenf6e9228b2016-01-26 18:04:35 -050053import com.android.internal.logging.MetricsProto.MetricsEvent;
Winsonc0d70582016-01-29 10:24:39 -080054import com.android.systemui.Interpolators;
Winson Chungd16c5652015-01-26 16:11:07 -080055import com.android.systemui.R;
Winsone7f138c2015-10-22 16:15:21 -070056import com.android.systemui.recents.Recents;
Winsonbe7607a2015-10-01 17:24:51 -070057import com.android.systemui.recents.RecentsActivity;
Winsonb1e71d02015-11-23 12:40:23 -080058import com.android.systemui.recents.RecentsActivityLaunchState;
Winson Chung303e1ff2014-03-07 15:06:19 -080059import com.android.systemui.recents.RecentsConfiguration;
Winsonc29ff002015-11-20 16:00:45 -080060import com.android.systemui.recents.RecentsDebugFlags;
Winson2536c7e2015-10-01 15:49:31 -070061import com.android.systemui.recents.events.EventBus;
Winson412e1802015-10-20 16:57:57 -070062import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
Jorim Jaggi192086e2016-03-11 17:17:03 +010063import com.android.systemui.recents.events.activity.DockedFirstAnimationFrameEvent;
Winson49df4202016-01-25 17:33:34 -080064import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
Winson8f6ee482016-03-18 17:51:48 -070065import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
Winson Chung48f2cda2015-12-11 13:20:12 -050066import com.android.systemui.recents.events.activity.LaunchTaskEvent;
Winson8f6ee482016-03-18 17:51:48 -070067import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
Jorim Jaggidd98d412015-11-18 15:57:38 -080068import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
69import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
Winson49df4202016-01-25 17:33:34 -080070import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
71import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
Winsoneca4ab62015-11-04 10:50:28 -080072import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
Winsonbe7607a2015-10-01 17:24:51 -070073import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
74import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
Winson Chung9a742902015-12-11 10:25:40 -050075import com.android.systemui.recents.misc.ReferenceCountedTrigger;
Winson Chung1f24c7e2014-07-11 17:06:48 -070076import com.android.systemui.recents.misc.SystemServicesProxy;
Winsonc5fd3502016-01-18 15:18:37 -080077import com.android.systemui.recents.misc.Utilities;
Winson Chung303e1ff2014-03-07 15:06:19 -080078import com.android.systemui.recents.model.Task;
79import com.android.systemui.recents.model.TaskStack;
Jorim Jaggic69bd222016-03-15 14:38:37 +010080import com.android.systemui.recents.views.RecentsTransitionHelper.AnimationSpecComposer;
Jorim Jaggi870ab5a2015-12-02 18:37:54 -080081import com.android.systemui.stackdivider.WindowManagerProxy;
82import com.android.systemui.statusbar.FlingAnimationUtils;
Winson Chung303e1ff2014-03-07 15:06:19 -080083
84import java.util.ArrayList;
Winson Chung6ac8bd62015-01-07 16:38:35 -080085import java.util.List;
Winson Chung303e1ff2014-03-07 15:06:19 -080086
Winson Chung303e1ff2014-03-07 15:06:19 -080087/**
88 * This view is the the top level layout that contains TaskStacks (which are laid out according
89 * to their SpaceNode bounds.
90 */
Winson Chung48f2cda2015-12-11 13:20:12 -050091public class RecentsView extends FrameLayout {
Winson Chung47c4c692014-03-17 10:17:11 -070092
Winson3e874742016-01-07 10:08:17 -080093 private static final int DOCK_AREA_OVERLAY_TRANSITION_DURATION = 135;
Winson49df4202016-01-25 17:33:34 -080094 private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
95 private static final float DEFAULT_SCRIM_ALPHA = 0.33f;
Jorim Jaggi6e18e002015-06-02 17:07:39 -070096
Winson Chung9a742902015-12-11 10:25:40 -050097 private final Handler mHandler;
Winson Chungd42a6cf2014-06-03 16:24:04 -070098
Winson Chung9a742902015-12-11 10:25:40 -050099 private TaskStack mStack;
100 private TaskStackView mTaskStackView;
Winson8f6ee482016-03-18 17:51:48 -0700101 private TextView mStackActionButton;
Winson196e8612016-03-15 15:20:17 -0700102 private TextView mEmptyView;
Winson49df4202016-01-25 17:33:34 -0800103
Winson Chung9a742902015-12-11 10:25:40 -0500104 private boolean mAwaitingFirstLayout = true;
105 private boolean mLastTaskLaunchedWasFreeform;
Winson231bc9c2016-02-09 12:31:00 -0800106
107 @ViewDebug.ExportedProperty(category="recents")
Winson Chung9a742902015-12-11 10:25:40 -0500108 private Rect mSystemInsets = new Rect();
Winson3e874742016-01-07 10:08:17 -0800109 private int mDividerSize;
Winsonbe7607a2015-10-01 17:24:51 -0700110
Winson49df4202016-01-25 17:33:34 -0800111 private ColorDrawable mBackgroundScrim = new ColorDrawable(Color.BLACK);
112 private Animator mBackgroundScrimAnimator;
113
Winson Chung9a742902015-12-11 10:25:40 -0500114 private RecentsTransitionHelper mTransitionHelper;
Winson231bc9c2016-02-09 12:31:00 -0800115 @ViewDebug.ExportedProperty(deepExport=true, prefix="touch_")
Winson Chung9a742902015-12-11 10:25:40 -0500116 private RecentsViewTouchHandler mTouchHandler;
Winson Chung9a742902015-12-11 10:25:40 -0500117 private final FlingAnimationUtils mFlingAnimationUtils;
Jorim Jaggi870ab5a2015-12-02 18:37:54 -0800118
Winson Chung303e1ff2014-03-07 15:06:19 -0800119 public RecentsView(Context context) {
Jorim Jaggi870ab5a2015-12-02 18:37:54 -0800120 this(context, null);
Winson Chung8e548f72014-06-24 14:40:53 -0700121 }
122
123 public RecentsView(Context context, AttributeSet attrs) {
124 this(context, attrs, 0);
125 }
126
127 public RecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
128 this(context, attrs, defStyleAttr, 0);
129 }
130
131 public RecentsView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
132 super(context, attrs, defStyleAttr, defStyleRes);
Winsonbe7607a2015-10-01 17:24:51 -0700133 setWillNotDraw(false);
Winson3e874742016-01-07 10:08:17 -0800134
135 SystemServicesProxy ssp = Recents.getSystemServices();
Winson83c1b072015-11-09 10:48:04 -0800136 mHandler = new Handler();
137 mTransitionHelper = new RecentsTransitionHelper(getContext(), mHandler);
Winson3e874742016-01-07 10:08:17 -0800138 mDividerSize = ssp.getDockedDividerSize(context);
Winsonbe7607a2015-10-01 17:24:51 -0700139 mTouchHandler = new RecentsViewTouchHandler(this);
Jorim Jaggi870ab5a2015-12-02 18:37:54 -0800140 mFlingAnimationUtils = new FlingAnimationUtils(context, 0.3f);
Winsonc29ff002015-11-20 16:00:45 -0800141
Winson49df4202016-01-25 17:33:34 -0800142 final float cornerRadius = context.getResources().getDimensionPixelSize(
143 R.dimen.recents_task_view_rounded_corners_radius);
Winsonc29ff002015-11-20 16:00:45 -0800144 LayoutInflater inflater = LayoutInflater.from(context);
Winson8f6ee482016-03-18 17:51:48 -0700145 if (RecentsDebugFlags.Static.EnableStackActionButton) {
146 mStackActionButton = (TextView) inflater.inflate(R.layout.recents_stack_action_button, this,
Winson91b225d2016-02-16 15:18:07 -0800147 false);
Winson8f6ee482016-03-18 17:51:48 -0700148 mStackActionButton.setOnClickListener(new View.OnClickListener() {
Winson91b225d2016-02-16 15:18:07 -0800149 @Override
150 public void onClick(View v) {
Winson8f6ee482016-03-18 17:51:48 -0700151 // TODO: To be implemented
Winson91b225d2016-02-16 15:18:07 -0800152 }
153 });
Winson8f6ee482016-03-18 17:51:48 -0700154 addView(mStackActionButton);
155 mStackActionButton.setClipToOutline(true);
156 mStackActionButton.setOutlineProvider(new ViewOutlineProvider() {
Winson91b225d2016-02-16 15:18:07 -0800157 @Override
158 public void getOutline(View view, Outline outline) {
159 outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), cornerRadius);
160 }
161 });
162 }
Winson196e8612016-03-15 15:20:17 -0700163 mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
Winson Chung9a742902015-12-11 10:25:40 -0500164 addView(mEmptyView);
Winson49df4202016-01-25 17:33:34 -0800165
166 setBackground(mBackgroundScrim);
Winson Chungd16c5652015-01-26 16:11:07 -0800167 }
168
Winson Chungdcfa7972014-07-22 12:27:13 -0700169 /** Set/get the bsp root node */
Winson59924fe2016-03-17 14:13:18 -0700170 public void onResume(boolean isResumingFromVisible, boolean multiWindowChange,
171 TaskStack stack) {
Winson53ec42c2015-10-28 15:55:35 -0700172 RecentsConfiguration config = Recents.getConfiguration();
Winson Chung9a742902015-12-11 10:25:40 -0500173 RecentsActivityLaunchState launchState = config.getLaunchState();
Winson88737542016-02-17 13:27:33 -0800174
Winson59924fe2016-03-17 14:13:18 -0700175 if (!multiWindowChange &&
176 (mTaskStackView == null || !launchState.launchedReuseTaskStackViews)) {
Winson88737542016-02-17 13:27:33 -0800177 isResumingFromVisible = false;
178 removeView(mTaskStackView);
179 mTaskStackView = new TaskStackView(getContext());
Winson59924fe2016-03-17 14:13:18 -0700180 mTaskStackView.setSystemInsets(mSystemInsets);
Winson88737542016-02-17 13:27:33 -0800181 mStack = mTaskStackView.getStack();
Winson147ecaf2015-09-16 16:49:55 -0700182 addView(mTaskStackView);
Winson Chung303e1ff2014-03-07 15:06:19 -0800183 }
Winson Chung9a742902015-12-11 10:25:40 -0500184
Winson88737542016-02-17 13:27:33 -0800185 // Reset the state
186 mAwaitingFirstLayout = !isResumingFromVisible;
187 mLastTaskLaunchedWasFreeform = false;
188
189 // Update the stack
190 mTaskStackView.onResume(isResumingFromVisible);
Winson4cfea692016-03-08 12:33:56 -0800191 mTaskStackView.setTasks(stack, isResumingFromVisible /* notifyStackChanges */,
Winson59924fe2016-03-17 14:13:18 -0700192 true /* relayoutTaskStack */, multiWindowChange);
Winson88737542016-02-17 13:27:33 -0800193
194 if (isResumingFromVisible) {
195 // If we are already visible, then restore the background scrim
196 animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
Winson49df4202016-01-25 17:33:34 -0800197 } else {
Winson88737542016-02-17 13:27:33 -0800198 // If we are already occluded by the app, then set the final background scrim alpha now.
199 // Otherwise, defer until the enter animation completes to animate the scrim alpha with
200 // the tasks for the home animation.
201 if (launchState.launchedWhileDocking || launchState.launchedFromApp
202 || mStack.getTaskCount() == 0) {
203 mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
204 } else {
205 mBackgroundScrim.setAlpha(0);
206 }
Winson49df4202016-01-25 17:33:34 -0800207 }
208
Winson Chung9a742902015-12-11 10:25:40 -0500209 // Update the top level view's visibilities
Winson4b057c62016-01-12 15:01:52 -0800210 if (stack.getTaskCount() > 0) {
Winson Chung9a742902015-12-11 10:25:40 -0500211 hideEmptyView();
Winsonc29ff002015-11-20 16:00:45 -0800212 } else {
Winson196e8612016-03-15 15:20:17 -0700213 showEmptyView(R.string.recents_empty_message);
Winsonc29ff002015-11-20 16:00:45 -0800214 }
Winson Chung19fc1172014-07-31 18:40:03 -0700215 }
216
Winsonb1e71d02015-11-23 12:40:23 -0800217 /**
218 * Returns whether the last task launched was in the freeform stack or not.
219 */
220 public boolean isLastTaskLaunchedFreeform() {
221 return mLastTaskLaunchedWasFreeform;
222 }
223
Winson Chung1e8d71b2014-05-16 17:05:22 -0700224 /** Launches the focused task from the first stack if possible */
Winson42329522016-02-05 10:39:46 -0800225 public boolean launchFocusedTask(int logEvent) {
Winson147ecaf2015-09-16 16:49:55 -0700226 if (mTaskStackView != null) {
Winson142af422015-11-09 10:39:57 -0800227 Task task = mTaskStackView.getFocusedTask();
228 if (task != null) {
229 TaskView taskView = mTaskStackView.getChildViewForTask(task);
Winson Chung48f2cda2015-12-11 13:20:12 -0500230 EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null,
231 INVALID_STACK_ID, false));
Winson42329522016-02-05 10:39:46 -0800232
233 if (logEvent != 0) {
234 MetricsLogger.action(getContext(), logEvent,
235 task.key.getComponent().toString());
236 }
Winson142af422015-11-09 10:39:57 -0800237 return true;
Winson Chung1e8d71b2014-05-16 17:05:22 -0700238 }
239 }
Winson Chung1e8d71b2014-05-16 17:05:22 -0700240 return false;
241 }
242
Winsona0731a12015-12-02 15:10:14 -0800243 /** Launches the task that recents was launched from if possible */
244 public boolean launchPreviousTask() {
245 if (mTaskStackView != null) {
246 TaskStack stack = mTaskStackView.getStack();
247 Task task = stack.getLaunchTarget();
248 if (task != null) {
249 TaskView taskView = mTaskStackView.getChildViewForTask(task);
Winson Chung48f2cda2015-12-11 13:20:12 -0500250 EventBus.getDefault().send(new LaunchTaskEvent(taskView, task, null,
251 INVALID_STACK_ID, false));
Winsona0731a12015-12-02 15:10:14 -0800252 return true;
253 }
254 }
255 return false;
256 }
257
Skuhne8aa7d162015-03-20 13:40:53 -0700258 /** Launches a given task. */
Filip Gruszczynskif48b5852015-10-13 10:28:22 -0700259 public boolean launchTask(Task task, Rect taskBounds, int destinationStack) {
Winson147ecaf2015-09-16 16:49:55 -0700260 if (mTaskStackView != null) {
Skuhne8aa7d162015-03-20 13:40:53 -0700261 // Iterate the stack views and try and find the given task.
Winson147ecaf2015-09-16 16:49:55 -0700262 List<TaskView> taskViews = mTaskStackView.getTaskViews();
Skuhne8aa7d162015-03-20 13:40:53 -0700263 int taskViewCount = taskViews.size();
264 for (int j = 0; j < taskViewCount; j++) {
265 TaskView tv = taskViews.get(j);
266 if (tv.getTask() == task) {
Winson Chung48f2cda2015-12-11 13:20:12 -0500267 EventBus.getDefault().send(new LaunchTaskEvent(tv, task, taskBounds,
268 destinationStack, false));
Skuhne8aa7d162015-03-20 13:40:53 -0700269 return true;
270 }
271 }
272 }
273 return false;
274 }
275
Winson Chung9a742902015-12-11 10:25:40 -0500276 /**
277 * Hides the task stack and shows the empty view.
278 */
Winson196e8612016-03-15 15:20:17 -0700279 public void showEmptyView(int msgResId) {
Winson Chung9a742902015-12-11 10:25:40 -0500280 mTaskStackView.setVisibility(View.INVISIBLE);
Winson196e8612016-03-15 15:20:17 -0700281 mEmptyView.setText(msgResId);
Winson Chung9a742902015-12-11 10:25:40 -0500282 mEmptyView.setVisibility(View.VISIBLE);
283 mEmptyView.bringToFront();
Winson8f6ee482016-03-18 17:51:48 -0700284 if (RecentsDebugFlags.Static.EnableStackActionButton) {
285 mStackActionButton.bringToFront();
Winson91b225d2016-02-16 15:18:07 -0800286 }
Winson Chung9a742902015-12-11 10:25:40 -0500287 }
288
289 /**
290 * Shows the task stack and hides the empty view.
291 */
292 public void hideEmptyView() {
293 mEmptyView.setVisibility(View.INVISIBLE);
294 mTaskStackView.setVisibility(View.VISIBLE);
Winson Chung9a742902015-12-11 10:25:40 -0500295 mTaskStackView.bringToFront();
Winson8f6ee482016-03-18 17:51:48 -0700296 if (RecentsDebugFlags.Static.EnableStackActionButton) {
297 mStackActionButton.bringToFront();
Winson91b225d2016-02-16 15:18:07 -0800298 }
Winson Chung772b6b12014-07-03 15:54:02 -0700299 }
300
Winsonbe7607a2015-10-01 17:24:51 -0700301 @Override
302 protected void onAttachedToWindow() {
303 EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
Winsonc8a4cdc2016-01-19 11:30:51 -0800304 EventBus.getDefault().register(mTouchHandler, RecentsActivity.EVENT_BUS_PRIORITY + 2);
Winsonbe7607a2015-10-01 17:24:51 -0700305 super.onAttachedToWindow();
306 }
307
308 @Override
309 protected void onDetachedFromWindow() {
310 super.onDetachedFromWindow();
311 EventBus.getDefault().unregister(this);
312 EventBus.getDefault().unregister(mTouchHandler);
313 }
314
Winson Chungf7bca432014-04-30 17:11:13 -0700315 /**
316 * This is called with the full size of the window since we are handling our own insets.
317 */
Winson Chung303e1ff2014-03-07 15:06:19 -0800318 @Override
319 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
320 int width = MeasureSpec.getSize(widthMeasureSpec);
321 int height = MeasureSpec.getSize(heightMeasureSpec);
Winson Chungbd912972014-03-18 14:36:35 -0700322
Winson59924fe2016-03-17 14:13:18 -0700323 if (mTaskStackView.getVisibility() != GONE) {
Winson147ecaf2015-09-16 16:49:55 -0700324 mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
Winson Chung303e1ff2014-03-07 15:06:19 -0800325 }
326
Winson49df4202016-01-25 17:33:34 -0800327 // Measure the empty view to the full size of the screen
328 if (mEmptyView.getVisibility() != GONE) {
Winson196e8612016-03-15 15:20:17 -0700329 measureChild(mEmptyView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
330 MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
Winson49df4202016-01-25 17:33:34 -0800331 }
Winson Chung9a742902015-12-11 10:25:40 -0500332
Winson8f6ee482016-03-18 17:51:48 -0700333 if (RecentsDebugFlags.Static.EnableStackActionButton) {
334 // Measure the stack action button within the constraints of the space above the stack
335 Rect actionButtonRect = mTaskStackView.mLayoutAlgorithm.mStackActionButtonRect;
336 measureChild(mStackActionButton,
337 MeasureSpec.makeMeasureSpec(actionButtonRect.width(), MeasureSpec.AT_MOST),
338 MeasureSpec.makeMeasureSpec(actionButtonRect.height(), MeasureSpec.AT_MOST));
Winson214f0f02016-01-26 13:37:37 -0800339 }
Winson Chung9a742902015-12-11 10:25:40 -0500340
Winson Chung303e1ff2014-03-07 15:06:19 -0800341 setMeasuredDimension(width, height);
342 }
343
Winson Chungf7bca432014-04-30 17:11:13 -0700344 /**
345 * This is called with the full size of the window since we are handling our own insets.
346 */
Winson Chung303e1ff2014-03-07 15:06:19 -0800347 @Override
348 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
Winson59924fe2016-03-17 14:13:18 -0700349 if (mTaskStackView.getVisibility() != GONE) {
Winson147ecaf2015-09-16 16:49:55 -0700350 mTaskStackView.layout(left, top, left + getMeasuredWidth(), top + getMeasuredHeight());
Winson Chung303e1ff2014-03-07 15:06:19 -0800351 }
Winsonbe7607a2015-10-01 17:24:51 -0700352
Winson Chung9a742902015-12-11 10:25:40 -0500353 // Layout the empty view
Winson49df4202016-01-25 17:33:34 -0800354 if (mEmptyView.getVisibility() != GONE) {
Winson196e8612016-03-15 15:20:17 -0700355 int leftRightInsets = mSystemInsets.left + mSystemInsets.right;
356 int topBottomInsets = mSystemInsets.top + mSystemInsets.bottom;
357 int childWidth = mEmptyView.getMeasuredWidth();
358 int childHeight = mEmptyView.getMeasuredHeight();
359 int childLeft = left + Math.max(0, (right - left - leftRightInsets - childWidth)) / 2;
360 int childTop = top + Math.max(0, (bottom - top - topBottomInsets - childHeight)) / 2;
361 mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
Winson49df4202016-01-25 17:33:34 -0800362 }
Winson Chung9a742902015-12-11 10:25:40 -0500363
Winson8f6ee482016-03-18 17:51:48 -0700364 if (RecentsDebugFlags.Static.EnableStackActionButton) {
365 // Layout the stack action button such that its drawable is start-aligned with the
366 // stack, vertically centered in the available space above the stack
367 Rect actionButtonRect = mTaskStackView.mLayoutAlgorithm.mStackActionButtonRect;
368 int buttonLeft = isLayoutRtl()
369 ? actionButtonRect.right + mStackActionButton.getPaddingStart()
370 - mStackActionButton.getMeasuredWidth()
371 : actionButtonRect.left - mStackActionButton.getPaddingStart();
372 int buttonTop = actionButtonRect.top +
373 (actionButtonRect.height() - mStackActionButton.getMeasuredHeight()) / 2;
374 mStackActionButton.layout(buttonLeft, buttonTop,
375 buttonLeft + mStackActionButton.getMeasuredWidth(),
376 buttonTop + mStackActionButton.getMeasuredHeight());
Winson214f0f02016-01-26 13:37:37 -0800377 }
378
Winsonb1e71d02015-11-23 12:40:23 -0800379 if (mAwaitingFirstLayout) {
380 mAwaitingFirstLayout = false;
381
382 // If launched via dragging from the nav bar, then we should translate the whole view
383 // down offscreen
384 RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
385 if (launchState.launchedViaDragGesture) {
386 setTranslationY(getMeasuredHeight());
Jorim Jaggi0ca88262015-12-07 17:15:16 -0800387 } else {
388 setTranslationY(0f);
Winsonb1e71d02015-11-23 12:40:23 -0800389 }
390 }
Winson Chung303e1ff2014-03-07 15:06:19 -0800391 }
392
Winson Chung8eaeb7d2014-06-25 15:10:59 -0700393 @Override
Winson Chung8eaeb7d2014-06-25 15:10:59 -0700394 public WindowInsets onApplyWindowInsets(WindowInsets insets) {
Winson35f30502015-09-28 11:24:36 -0700395 mSystemInsets.set(insets.getSystemWindowInsets());
Winson59924fe2016-03-17 14:13:18 -0700396 mTaskStackView.setSystemInsets(mSystemInsets);
Winson Chung8eaeb7d2014-06-25 15:10:59 -0700397 requestLayout();
Winsonc29ff002015-11-20 16:00:45 -0800398 return insets;
Winson Chung8eaeb7d2014-06-25 15:10:59 -0700399 }
400
Winsonbe7607a2015-10-01 17:24:51 -0700401 @Override
402 public boolean onInterceptTouchEvent(MotionEvent ev) {
403 return mTouchHandler.onInterceptTouchEvent(ev);
404 }
405
406 @Override
407 public boolean onTouchEvent(MotionEvent ev) {
408 return mTouchHandler.onTouchEvent(ev);
409 }
410
411 @Override
Winsonbe8e6962016-02-01 14:27:52 -0800412 public void onDrawForeground(Canvas canvas) {
413 super.onDrawForeground(canvas);
414
Winson036693c2016-01-14 17:16:06 -0800415 ArrayList<TaskStack.DockState> visDockStates = mTouchHandler.getVisibleDockStates();
416 for (int i = visDockStates.size() - 1; i >= 0; i--) {
417 Drawable d = visDockStates.get(i).viewState.dockAreaOverlay;
Winson882072b2015-10-12 11:26:33 -0700418 if (d.getAlpha() > 0) {
419 d.draw(canvas);
420 }
Winsonbe7607a2015-10-01 17:24:51 -0700421 }
422 }
423
Winson4165d3362015-10-10 14:40:35 -0700424 @Override
425 protected boolean verifyDrawable(Drawable who) {
Winson036693c2016-01-14 17:16:06 -0800426 ArrayList<TaskStack.DockState> visDockStates = mTouchHandler.getVisibleDockStates();
427 for (int i = visDockStates.size() - 1; i >= 0; i--) {
428 Drawable d = visDockStates.get(i).viewState.dockAreaOverlay;
Winson882072b2015-10-12 11:26:33 -0700429 if (d == who) {
430 return true;
431 }
432 }
433 return super.verifyDrawable(who);
Winson4165d3362015-10-10 14:40:35 -0700434 }
435
Winsonbe7607a2015-10-01 17:24:51 -0700436 /**** EventBus Events ****/
437
Winson Chung48f2cda2015-12-11 13:20:12 -0500438 public final void onBusEvent(LaunchTaskEvent event) {
439 mLastTaskLaunchedWasFreeform = event.task.isFreeformTask();
440 mTransitionHelper.launchTaskFromRecents(mStack, event.task, mTaskStackView, event.taskView,
441 event.screenPinningRequested, event.targetTaskBounds, event.targetTaskStack);
442 }
443
Winsonef064132016-01-05 12:11:31 -0800444 public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
Winson50448632016-02-01 18:04:59 -0800445 int taskViewExitToHomeDuration = TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION;
Winson8f6ee482016-03-18 17:51:48 -0700446 if (RecentsDebugFlags.Static.EnableStackActionButton) {
447 // Hide the stack action button
448 hideStackActionButton(taskViewExitToHomeDuration, false /* translate */);
Winson91b225d2016-02-16 15:18:07 -0800449 }
Winson49df4202016-01-25 17:33:34 -0800450 animateBackgroundScrim(0f, taskViewExitToHomeDuration);
Winsonef064132016-01-05 12:11:31 -0800451 }
452
Winsonbe7607a2015-10-01 17:24:51 -0700453 public final void onBusEvent(DragStartEvent event) {
Winson882072b2015-10-12 11:26:33 -0700454 updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(),
Winson3e874742016-01-07 10:08:17 -0800455 true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha,
456 true /* animateAlpha */, false /* animateBounds */);
Winsonbe7607a2015-10-01 17:24:51 -0700457 }
458
Winsoneca4ab62015-11-04 10:50:28 -0800459 public final void onBusEvent(DragDropTargetChangedEvent event) {
460 if (event.dropTarget == null || !(event.dropTarget instanceof TaskStack.DockState)) {
Winson882072b2015-10-12 11:26:33 -0700461 updateVisibleDockRegions(mTouchHandler.getDockStatesForCurrentOrientation(),
Winson3e874742016-01-07 10:08:17 -0800462 true /* isDefaultDockState */, TaskStack.DockState.NONE.viewState.dockAreaAlpha,
463 true /* animateAlpha */, true /* animateBounds */);
Winson882072b2015-10-12 11:26:33 -0700464 } else {
Winsoneca4ab62015-11-04 10:50:28 -0800465 final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
Winson3e874742016-01-07 10:08:17 -0800466 updateVisibleDockRegions(new TaskStack.DockState[] {dockState},
467 false /* isDefaultDockState */, -1, true /* animateAlpha */,
468 true /* animateBounds */);
Winson882072b2015-10-12 11:26:33 -0700469 }
Winsonbe7607a2015-10-01 17:24:51 -0700470 }
471
472 public final void onBusEvent(final DragEndEvent event) {
Winson479f7442015-11-25 15:16:27 -0800473 // Handle the case where we drop onto a dock region
474 if (event.dropTarget instanceof TaskStack.DockState) {
Winson3e874742016-01-07 10:08:17 -0800475 final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
476
477 // Hide the dock region
478 updateVisibleDockRegions(null, false /* isDefaultDockState */, -1,
479 false /* animateAlpha */, false /* animateBounds */);
480
Winsonf24f2162016-01-05 12:11:55 -0800481 TaskStackLayoutAlgorithm stackLayout = mTaskStackView.getStackAlgorithm();
482 TaskStackViewScroller stackScroller = mTaskStackView.getScroller();
483 TaskViewTransform tmpTransform = new TaskViewTransform();
Winsoneca4ab62015-11-04 10:50:28 -0800484
Winson3e874742016-01-07 10:08:17 -0800485 // We translated the view but we need to animate it back from the current layout-space
486 // rect to its final layout-space rect
487 int x = (int) event.taskView.getTranslationX();
488 int y = (int) event.taskView.getTranslationY();
489 Rect taskViewRect = new Rect(event.taskView.getLeft(), event.taskView.getTop(),
490 event.taskView.getRight(), event.taskView.getBottom());
491 taskViewRect.offset(x, y);
492 event.taskView.setTranslationX(0);
493 event.taskView.setTranslationY(0);
494 event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
495 taskViewRect.right, taskViewRect.bottom);
496
Jorim Jaggi192086e2016-03-11 17:17:03 +0100497 final OnAnimationStartedListener startedListener = new OnAnimationStartedListener() {
498 @Override
499 public void onAnimationStarted() {
500 EventBus.getDefault().send(new DockedFirstAnimationFrameEvent());
501 mTaskStackView.getStack().removeTask(event.task, AnimationProps.IMMEDIATE,
502 true /* fromDockGesture */);
503 }
504 };
Jorim Jaggic69bd222016-03-15 14:38:37 +0100505
506 // Dock the task and launch it
507 SystemServicesProxy ssp = Recents.getSystemServices();
508 ssp.startTaskInDockedMode(event.task.key.id, dockState.createMode);
509 final Rect taskRect = getTaskRect(event.taskView);
510 IAppTransitionAnimationSpecsFuture future = mTransitionHelper.getAppTransitionFuture(
511 new AnimationSpecComposer() {
512 @Override
513 public List<AppTransitionAnimationSpec> composeSpecs() {
514 return mTransitionHelper.composeDockAnimationSpec(
515 event.taskView, taskRect);
516 }
517 });
518 ssp.overridePendingAppTransitionMultiThumbFuture(future,
519 mTransitionHelper.wrapStartedListener(startedListener),
520 true /* scaleUp */);
Winsona0a8ae42015-12-01 10:43:02 -0800521
Chris Wrenf6e9228b2016-01-26 18:04:35 -0500522 MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_DRAG_DROP);
Winson3e874742016-01-07 10:08:17 -0800523 } else {
524 // Animate the overlay alpha back to 0
525 updateVisibleDockRegions(null, true /* isDefaultDockState */, -1,
526 true /* animateAlpha */, false /* animateBounds */);
Winsonbe7607a2015-10-01 17:24:51 -0700527 }
528 }
Winson4165d3362015-10-10 14:40:35 -0700529
Jorim Jaggic69bd222016-03-15 14:38:37 +0100530 private Rect getTaskRect(TaskView taskView) {
531 int[] location = taskView.getLocationOnScreen();
532 int viewX = location[0];
533 int viewY = location[1];
534 return new Rect(viewX, viewY,
535 (int) (viewX + taskView.getWidth() * taskView.getScaleX()),
536 (int) (viewY + taskView.getHeight() * taskView.getScaleY()));
537 }
538
Jorim Jaggidd98d412015-11-18 15:57:38 -0800539 public final void onBusEvent(DraggingInRecentsEvent event) {
Jorim Jaggi54b1a6d2015-11-24 17:48:26 -0800540 if (mTaskStackView.getTaskViews().size() > 0) {
541 setTranslationY(event.distanceFromTop - mTaskStackView.getTaskViews().get(0).getY());
542 }
Jorim Jaggidd98d412015-11-18 15:57:38 -0800543 }
544
545 public final void onBusEvent(DraggingInRecentsEndedEvent event) {
Jorim Jaggi870ab5a2015-12-02 18:37:54 -0800546 ViewPropertyAnimator animator = animate();
Jorim Jaggi8fccfe22015-12-03 16:58:08 -0800547 if (event.velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
Jorim Jaggi870ab5a2015-12-02 18:37:54 -0800548 animator.translationY(getHeight());
549 animator.withEndAction(new Runnable() {
550 @Override
551 public void run() {
552 WindowManagerProxy.getInstance().maximizeDockedStack();
553 }
554 });
555 mFlingAnimationUtils.apply(animator, getTranslationY(), getHeight(), event.velocity);
556 } else {
557 animator.translationY(0f);
558 animator.setListener(null);
559 mFlingAnimationUtils.apply(animator, getTranslationY(), 0, event.velocity);
560 }
561 animator.start();
Jorim Jaggidd98d412015-11-18 15:57:38 -0800562 }
563
Winson49df4202016-01-25 17:33:34 -0800564 public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
565 RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
Winsone693aaf2016-03-01 12:05:59 -0800566 if (!launchState.launchedWhileDocking && !launchState.launchedFromApp
Jorim Jaggie161f082016-02-05 14:26:16 -0800567 && mStack.getTaskCount() > 0) {
Winson50448632016-02-01 18:04:59 -0800568 animateBackgroundScrim(DEFAULT_SCRIM_ALPHA,
569 TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);
Winson49df4202016-01-25 17:33:34 -0800570 }
571 }
572
573 public final void onBusEvent(UpdateBackgroundScrimEvent event) {
574 animateBackgroundScrim(event.alpha, DEFAULT_UPDATE_SCRIM_DURATION);
575 }
576
577 public final void onBusEvent(ResetBackgroundScrimEvent event) {
578 animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
579 }
580
Winson8f6ee482016-03-18 17:51:48 -0700581 public final void onBusEvent(ShowStackActionButtonEvent event) {
582 if (!RecentsDebugFlags.Static.EnableStackActionButton) {
Winson91b225d2016-02-16 15:18:07 -0800583 return;
584 }
585
Winson8f6ee482016-03-18 17:51:48 -0700586 showStackActionButton(150, event.translate);
Winson49df4202016-01-25 17:33:34 -0800587 }
588
Winson8f6ee482016-03-18 17:51:48 -0700589 public final void onBusEvent(HideStackActionButtonEvent event) {
590 if (!RecentsDebugFlags.Static.EnableStackActionButton) {
Winson91b225d2016-02-16 15:18:07 -0800591 return;
592 }
593
Winson8f6ee482016-03-18 17:51:48 -0700594 hideStackActionButton(100, true /* translate */);
Winson49df4202016-01-25 17:33:34 -0800595 }
596
Winsonc29ff002015-11-20 16:00:45 -0800597 /**
Winson8f6ee482016-03-18 17:51:48 -0700598 * Shows the stack action button.
Winsonc29ff002015-11-20 16:00:45 -0800599 */
Winson8f6ee482016-03-18 17:51:48 -0700600 private void showStackActionButton(final int duration, final boolean translate) {
601 if (!RecentsDebugFlags.Static.EnableStackActionButton) {
Winson91b225d2016-02-16 15:18:07 -0800602 return;
603 }
604
Winson49df4202016-01-25 17:33:34 -0800605 final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
Winson8f6ee482016-03-18 17:51:48 -0700606 if (mStackActionButton.getVisibility() == View.INVISIBLE) {
607 mStackActionButton.setVisibility(View.VISIBLE);
608 mStackActionButton.setAlpha(0f);
Winson49df4202016-01-25 17:33:34 -0800609 if (translate) {
Winson8f6ee482016-03-18 17:51:48 -0700610 mStackActionButton.setTranslationY(-mStackActionButton.getMeasuredHeight() * 0.25f);
Winson214f0f02016-01-26 13:37:37 -0800611 } else {
Winson8f6ee482016-03-18 17:51:48 -0700612 mStackActionButton.setTranslationY(0f);
Winson49df4202016-01-25 17:33:34 -0800613 }
614 postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
Winsonf24f2162016-01-05 12:11:55 -0800615 @Override
616 public void run() {
Winson49df4202016-01-25 17:33:34 -0800617 if (translate) {
Winson8f6ee482016-03-18 17:51:48 -0700618 mStackActionButton.animate()
Winson49df4202016-01-25 17:33:34 -0800619 .translationY(0f);
620 }
Winson8f6ee482016-03-18 17:51:48 -0700621 mStackActionButton.animate()
Winsonf24f2162016-01-05 12:11:55 -0800622 .alpha(1f)
623 .setDuration(duration)
Winsonc0d70582016-01-29 10:24:39 -0800624 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
Winsonf24f2162016-01-05 12:11:55 -0800625 .withLayer()
626 .start();
627 }
628 });
629 }
Winson49df4202016-01-25 17:33:34 -0800630 postAnimationTrigger.flushLastDecrementRunnables();
Winsonc29ff002015-11-20 16:00:45 -0800631 }
632
633 /**
Winson8f6ee482016-03-18 17:51:48 -0700634 * Hides the stack action button.
Winsonc29ff002015-11-20 16:00:45 -0800635 */
Winson8f6ee482016-03-18 17:51:48 -0700636 private void hideStackActionButton(int duration, boolean translate) {
637 if (!RecentsDebugFlags.Static.EnableStackActionButton) {
Winson91b225d2016-02-16 15:18:07 -0800638 return;
639 }
640
Winson49df4202016-01-25 17:33:34 -0800641 final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
Winson8f6ee482016-03-18 17:51:48 -0700642 hideStackActionButton(duration, translate, postAnimationTrigger);
Winson Chungaaeaac12015-12-16 16:49:36 -0500643 postAnimationTrigger.flushLastDecrementRunnables();
Winson Chung9a742902015-12-11 10:25:40 -0500644 }
645
Winson49df4202016-01-25 17:33:34 -0800646 /**
Winson8f6ee482016-03-18 17:51:48 -0700647 * Hides the stack action button.
Winson49df4202016-01-25 17:33:34 -0800648 */
Winson8f6ee482016-03-18 17:51:48 -0700649 private void hideStackActionButton(int duration, boolean translate,
650 final ReferenceCountedTrigger postAnimationTrigger) {
651 if (!RecentsDebugFlags.Static.EnableStackActionButton) {
Winson91b225d2016-02-16 15:18:07 -0800652 return;
653 }
654
Winson8f6ee482016-03-18 17:51:48 -0700655 if (mStackActionButton.getVisibility() == View.VISIBLE) {
Winson49df4202016-01-25 17:33:34 -0800656 if (translate) {
Winson8f6ee482016-03-18 17:51:48 -0700657 mStackActionButton.animate()
658 .translationY(-mStackActionButton.getMeasuredHeight() * 0.25f);
Winson49df4202016-01-25 17:33:34 -0800659 }
Winson8f6ee482016-03-18 17:51:48 -0700660 mStackActionButton.animate()
Winsonf24f2162016-01-05 12:11:55 -0800661 .alpha(0f)
662 .setDuration(duration)
Winsonc0d70582016-01-29 10:24:39 -0800663 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
Winsonf24f2162016-01-05 12:11:55 -0800664 .withEndAction(new Runnable() {
665 @Override
666 public void run() {
Winson8f6ee482016-03-18 17:51:48 -0700667 mStackActionButton.setVisibility(View.INVISIBLE);
Winson49df4202016-01-25 17:33:34 -0800668 postAnimationTrigger.decrement();
Winsonf24f2162016-01-05 12:11:55 -0800669 }
670 })
671 .withLayer()
672 .start();
Winson49df4202016-01-25 17:33:34 -0800673 postAnimationTrigger.increment();
Winsonf24f2162016-01-05 12:11:55 -0800674 }
Winsonc29ff002015-11-20 16:00:45 -0800675 }
676
Winson4165d3362015-10-10 14:40:35 -0700677 /**
678 * Updates the dock region to match the specified dock state.
679 */
Winson3e874742016-01-07 10:08:17 -0800680 private void updateVisibleDockRegions(TaskStack.DockState[] newDockStates,
681 boolean isDefaultDockState, int overrideAlpha, boolean animateAlpha,
682 boolean animateBounds) {
Winsonc5fd3502016-01-18 15:18:37 -0800683 ArraySet<TaskStack.DockState> newDockStatesSet = Utilities.arrayToSet(newDockStates,
684 new ArraySet<TaskStack.DockState>());
Winson036693c2016-01-14 17:16:06 -0800685 ArrayList<TaskStack.DockState> visDockStates = mTouchHandler.getVisibleDockStates();
686 for (int i = visDockStates.size() - 1; i >= 0; i--) {
687 TaskStack.DockState dockState = visDockStates.get(i);
Winson882072b2015-10-12 11:26:33 -0700688 TaskStack.DockState.ViewState viewState = dockState.viewState;
689 if (newDockStates == null || !newDockStatesSet.contains(dockState)) {
690 // This is no longer visible, so hide it
Winson3e874742016-01-07 10:08:17 -0800691 viewState.startAnimation(null, 0, DOCK_AREA_OVERLAY_TRANSITION_DURATION,
Winsonc0d70582016-01-29 10:24:39 -0800692 Interpolators.ALPHA_OUT, animateAlpha, animateBounds);
Winson882072b2015-10-12 11:26:33 -0700693 } else {
694 // This state is now visible, update the bounds and show it
695 int alpha = (overrideAlpha != -1 ? overrideAlpha : viewState.dockAreaAlpha);
Winson3e874742016-01-07 10:08:17 -0800696 Rect bounds = isDefaultDockState
697 ? dockState.getPreDockedBounds(getMeasuredWidth(), getMeasuredHeight())
698 : dockState.getDockedBounds(getMeasuredWidth(), getMeasuredHeight(),
699 mDividerSize, mSystemInsets, getResources());
700 if (viewState.dockAreaOverlay.getCallback() != this) {
701 viewState.dockAreaOverlay.setCallback(this);
702 viewState.dockAreaOverlay.setBounds(bounds);
703 }
704 viewState.startAnimation(bounds, alpha, DOCK_AREA_OVERLAY_TRANSITION_DURATION,
Winsonc0d70582016-01-29 10:24:39 -0800705 Interpolators.ALPHA_IN, animateAlpha, animateBounds);
Winson882072b2015-10-12 11:26:33 -0700706 }
Winson4165d3362015-10-10 14:40:35 -0700707 }
Winson4165d3362015-10-10 14:40:35 -0700708 }
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800709
Winson49df4202016-01-25 17:33:34 -0800710 /**
711 * Animates the background scrim to the given {@param alpha}.
712 */
713 private void animateBackgroundScrim(float alpha, int duration) {
714 Utilities.cancelAnimationWithoutCallbacks(mBackgroundScrimAnimator);
715 int alphaInt = (int) (alpha * 255);
716 mBackgroundScrimAnimator = ObjectAnimator.ofInt(mBackgroundScrim, Utilities.DRAWABLE_ALPHA,
717 mBackgroundScrim.getAlpha(), alphaInt);
718 mBackgroundScrimAnimator.setDuration(duration);
719 mBackgroundScrimAnimator.setInterpolator(alphaInt > mBackgroundScrim.getAlpha()
Winsonc0d70582016-01-29 10:24:39 -0800720 ? Interpolators.ALPHA_OUT
721 : Interpolators.ALPHA_IN);
Winson49df4202016-01-25 17:33:34 -0800722 mBackgroundScrimAnimator.start();
Filip Gruszczynski14b4e572015-11-03 15:53:55 -0800723 }
Winson Chung303e1ff2014-03-07 15:06:19 -0800724}