Methods Summary |
---|
void | clipTaskViews()Updates the clip for each of the task views.
// Update the clip on each task child
if (Constants.DebugFlags.App.EnableTaskStackClipping) {
int childCount = getChildCount();
for (int i = 0; i < childCount - 1; i++) {
TaskView tv = (TaskView) getChildAt(i);
TaskView nextTv = null;
TaskView tmpTv = null;
int clipBottom = 0;
if (tv.shouldClipViewInStack()) {
// Find the next view to clip against
int nextIndex = i;
while (nextIndex < getChildCount()) {
tmpTv = (TaskView) getChildAt(++nextIndex);
if (tmpTv != null && tmpTv.shouldClipViewInStack()) {
nextTv = tmpTv;
break;
}
}
// Clip against the next view, this is just an approximation since we are
// stacked and we can make assumptions about the visibility of the this
// task relative to the ones in front of it.
if (nextTv != null) {
// Map the top edge of next task view into the local space of the current
// task view to find the clip amount in local space
mTmpCoord[0] = mTmpCoord[1] = 0;
Utilities.mapCoordInDescendentToSelf(nextTv, this, mTmpCoord, false);
Utilities.mapCoordInSelfToDescendent(tv, this, mTmpCoord, mTmpMatrix);
clipBottom = (int) Math.floor(tv.getMeasuredHeight() - mTmpCoord[1]
- nextTv.getPaddingTop() - 1);
}
}
tv.getViewBounds().setClipBottom(clipBottom);
}
if (getChildCount() > 0) {
// The front most task should never be clipped
TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
tv.getViewBounds().setClipBottom(0);
}
}
mStackViewsClipDirty = false;
|
public void | computeRects(int windowWidth, int windowHeight, android.graphics.Rect taskStackBounds, boolean launchedWithAltTab, boolean launchedFromHome)Computes the stack and task rects
// Compute the rects in the stack algorithm
mLayoutAlgorithm.computeRects(windowWidth, windowHeight, taskStackBounds);
// Update the scroll bounds
updateMinMaxScroll(false, launchedWithAltTab, launchedFromHome);
|
public void | computeScroll()
mStackScroller.computeScroll();
// Synchronize the views
synchronizeStackViewsWithModel();
clipTaskViews();
// Notify accessibility
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
|
public TaskStackViewLayoutAlgorithm.VisibilityReport | computeStackVisibilityReport()Computes the maximum number of visible tasks and thumbnails. Requires that
updateMinMaxScrollForStack() is called first.
return mLayoutAlgorithm.computeStackVisibilityReport(mStack.getTasks());
|
public TaskView | createView(android.content.Context context)ViewPoolConsumer Implementation
return (TaskView) mInflater.inflate(R.layout.recents_task_view, this, false);
|
public void | dismissFocusedTask()Dismisses the focused task.
// Return early if the focused task index is invalid
if (mFocusedTaskIndex < 0 || mFocusedTaskIndex >= mStack.getTaskCount()) {
mFocusedTaskIndex = -1;
return;
}
Task t = mStack.getTasks().get(mFocusedTaskIndex);
TaskView tv = getChildViewForTask(t);
tv.dismissTask();
|
public boolean | ensureFocusedTask()Ensures that there is a task focused, if nothing is focused, then we will use the task
at the center of the visible stack.
if (mFocusedTaskIndex < 0) {
// If there is no task focused, then find the task that is closes to the center
// of the screen and use that as the currently focused task
int x = mLayoutAlgorithm.mStackVisibleRect.centerX();
int y = mLayoutAlgorithm.mStackVisibleRect.centerY();
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
tv.getHitRect(mTmpRect);
if (mTmpRect.contains(x, y)) {
mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
break;
}
}
// If we can't find the center task, then use the front most index
if (mFocusedTaskIndex < 0 && childCount > 0) {
mFocusedTaskIndex = childCount - 1;
}
}
return mFocusedTaskIndex >= 0;
|
public void | focusNextTask(boolean forward, boolean animateFocusedState)Focuses the next task in the stack.
// Find the next index to focus
int numTasks = mStack.getTaskCount();
if (numTasks == 0) return;
int direction = (forward ? -1 : 1);
int newIndex = mFocusedTaskIndex + direction;
if (newIndex >= 0 && newIndex <= (numTasks - 1)) {
newIndex = Math.max(0, Math.min(numTasks - 1, newIndex));
focusTask(newIndex, true, animateFocusedState);
}
|
void | focusTask(int taskIndex, boolean scrollToNewPosition, boolean animateFocusedState)Focuses the task at the specified index in the stack
// Return early if the task is already focused
if (taskIndex == mFocusedTaskIndex) return;
if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
mFocusedTaskIndex = taskIndex;
// Focus the view if possible, otherwise, focus the view after we scroll into position
Task t = mStack.getTasks().get(taskIndex);
TaskView tv = getChildViewForTask(t);
Runnable postScrollRunnable = null;
if (tv != null) {
tv.setFocusedTask(animateFocusedState);
} else {
postScrollRunnable = new Runnable() {
@Override
public void run() {
Task t = mStack.getTasks().get(mFocusedTaskIndex);
TaskView tv = getChildViewForTask(t);
if (tv != null) {
tv.setFocusedTask(animateFocusedState);
}
}
};
}
// Scroll the view into position (just center it in the curve)
if (scrollToNewPosition) {
float newScroll = mLayoutAlgorithm.getStackScrollForTask(t) - 0.5f;
newScroll = mStackScroller.getBoundedStackScroll(newScroll);
mStackScroller.animateScroll(mStackScroller.getStackScroll(), newScroll, postScrollRunnable);
} else {
if (postScrollRunnable != null) {
postScrollRunnable.run();
}
}
}
|
public TaskView | getChildViewForTask(com.android.systemui.recents.model.Task t)Finds the child view given a specific task.
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
if (tv.getTask() == t) {
return tv;
}
}
return null;
|
public TaskStackViewScroller | getScroller()Returns the scroller.
return mStackScroller;
|
public TaskStackViewLayoutAlgorithm | getStackAlgorithm()Returns the stack algorithm for this task stack.
return mLayoutAlgorithm;
|
public boolean | hasPreferredData(TaskView tv, com.android.systemui.recents.model.Task preferredData)
return (tv.getTask() == preferredData);
|
public boolean | isTransformedTouchPointInView(float x, float y, android.view.View child)
return isTransformedTouchPointInView(x, y, child, null);
|
void | onFirstLayout()Handler for the first layout.
int offscreenY = mLayoutAlgorithm.mViewRect.bottom -
(mLayoutAlgorithm.mTaskRect.top - mLayoutAlgorithm.mViewRect.top);
// Find the launch target task
Task launchTargetTask = null;
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
if (task.isLaunchTarget) {
launchTargetTask = task;
break;
}
}
// Prepare the first view for its enter animation
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
boolean occludesLaunchTarget = (launchTargetTask != null) &&
launchTargetTask.group.isTaskAboveTask(task, launchTargetTask);
tv.prepareEnterRecentsAnimation(task.isLaunchTarget, occludesLaunchTarget, offscreenY);
}
// If the enter animation started already and we haven't completed a layout yet, do the
// enter animation now
if (mStartEnterAnimationRequestedAfterLayout) {
startEnterRecentsAnimation(mStartEnterAnimationContext);
mStartEnterAnimationRequestedAfterLayout = false;
mStartEnterAnimationContext = null;
}
// When Alt-Tabbing, focus the previous task (but leave the animation until we finish the
// enter animation).
if (mConfig.launchedWithAltTab) {
if (mConfig.launchedFromAppWithThumbnail) {
focusTask(Math.max(0, mStack.getTaskCount() - 2), false,
mConfig.launchedHasConfigurationChanged);
} else {
focusTask(Math.max(0, mStack.getTaskCount() - 1), false,
mConfig.launchedHasConfigurationChanged);
}
}
// Start dozing
mUIDozeTrigger.startDozing();
|
public boolean | onGenericMotionEvent(android.view.MotionEvent ev)
return mTouchHandler.onGenericMotionEvent(ev);
|
public void | onInitializeAccessibilityEvent(android.view.accessibility.AccessibilityEvent event)
super.onInitializeAccessibilityEvent(event);
int childCount = getChildCount();
if (childCount > 0) {
TaskView backMostTask = (TaskView) getChildAt(0);
TaskView frontMostTask = (TaskView) getChildAt(childCount - 1);
event.setFromIndex(mStack.indexOfTask(backMostTask.getTask()));
event.setToIndex(mStack.indexOfTask(frontMostTask.getTask()));
event.setContentDescription(frontMostTask.getTask().activityLabel);
}
event.setItemCount(mStack.getTaskCount());
event.setScrollY(mStackScroller.mScroller.getCurrY());
event.setMaxScrollY(mStackScroller.progressToScrollRange(mLayoutAlgorithm.mMaxScrollP));
|
public boolean | onInterceptTouchEvent(android.view.MotionEvent ev)
return mTouchHandler.onInterceptTouchEvent(ev);
|
protected void | onLayout(boolean changed, int left, int top, int right, int bottom)This is called with the size of the space not including the top or right insets, or the
search bar height in portrait (but including the search bar width in landscape, since we want
to draw under it.
// Layout each of the children
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
if (tv.getBackground() != null) {
tv.getBackground().getPadding(mTmpRect);
} else {
mTmpRect.setEmpty();
}
tv.layout(mLayoutAlgorithm.mTaskRect.left - mTmpRect.left,
mLayoutAlgorithm.mTaskRect.top - mTmpRect.top,
mLayoutAlgorithm.mTaskRect.right + mTmpRect.right,
mLayoutAlgorithm.mTaskRect.bottom + mTmpRect.bottom);
}
if (mAwaitingFirstLayout) {
mAwaitingFirstLayout = false;
onFirstLayout();
}
|
protected void | onMeasure(int widthMeasureSpec, int heightMeasureSpec)This is called with the full window width and height to allow stack view children to
perform the full screen transition down.
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
// Compute our stack/task rects
Rect taskStackBounds = new Rect(mTaskStackBounds);
taskStackBounds.bottom -= mConfig.systemInsets.bottom;
computeRects(width, height, taskStackBounds, mConfig.launchedWithAltTab,
mConfig.launchedFromHome);
// If this is the first layout, then scroll to the front of the stack and synchronize the
// stack views immediately to load all the views
if (mAwaitingFirstLayout) {
mStackScroller.setStackScrollToInitialState();
requestSynchronizeStackViewsWithModel();
synchronizeStackViewsWithModel();
}
// Measure each of the TaskViews
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
if (tv.getBackground() != null) {
tv.getBackground().getPadding(mTmpRect);
} else {
mTmpRect.setEmpty();
}
tv.measure(
MeasureSpec.makeMeasureSpec(
mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right,
MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(
mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom,
MeasureSpec.EXACTLY));
}
setMeasuredDimension(width, height);
|
public void | onPackagesChanged(com.android.systemui.recents.model.RecentsPackageMonitor monitor, java.lang.String packageName, int userId)RecentsPackageMonitor.PackageCallbacks Implementation
// Compute which components need to be removed
HashSet<ComponentName> removedComponents = monitor.computeComponentsRemoved(
mStack.getTaskKeys(), packageName, userId);
// For other tasks, just remove them directly if they no longer exist
ArrayList<Task> tasks = mStack.getTasks();
for (int i = tasks.size() - 1; i >= 0; i--) {
final Task t = tasks.get(i);
if (removedComponents.contains(t.key.baseIntent.getComponent())) {
TaskView tv = getChildViewForTask(t);
if (tv != null) {
// For visible children, defer removing the task until after the animation
tv.startDeleteTaskAnimation(new Runnable() {
@Override
public void run() {
mStack.removeTask(t);
}
});
} else {
// Otherwise, remove the task from the stack immediately
mStack.removeTask(t);
}
}
}
|
void | onRecentsHidden()Final callback after Recents is finally hidden.
reset();
|
public void | onScrollChanged(float p)TaskStackViewScroller.TaskStackViewScrollerCallbacks
mUIDozeTrigger.poke();
requestSynchronizeStackViewsWithModel();
postInvalidateOnAnimation();
|
public void | onStackFiltered(com.android.systemui.recents.model.TaskStack newStack, java.util.ArrayList curTasks, com.android.systemui.recents.model.Task filteredTask)
/*
// Stash the scroll and filtered task for us to restore to when we unfilter
mStashedScroll = getStackScroll();
// Calculate the current task transforms
ArrayList<TaskViewTransform> curTaskTransforms =
getStackTransforms(curTasks, getStackScroll(), null, true);
// Update the task offsets
mLayoutAlgorithm.updateTaskOffsets(mStack.getTasks());
// Scroll the item to the top of the stack (sans-peek) rect so that we can see it better
updateMinMaxScroll(false);
float overlapHeight = mLayoutAlgorithm.getTaskOverlapHeight();
setStackScrollRaw((int) (newStack.indexOfTask(filteredTask) * overlapHeight));
boundScrollRaw();
// Compute the transforms of the items in the new stack after setting the new scroll
final ArrayList<Task> tasks = mStack.getTasks();
final ArrayList<TaskViewTransform> taskTransforms =
getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
// Animate
mFilterAlgorithm.startFilteringAnimation(curTasks, curTaskTransforms, tasks, taskTransforms);
// Notify any callbacks
mCb.onTaskStackFilterTriggered();
*/
|
public void | onStackTaskAdded(com.android.systemui.recents.model.TaskStack stack, com.android.systemui.recents.model.Task t)TaskStackCallbacks Implementation
requestSynchronizeStackViewsWithModel();
|
public void | onStackTaskRemoved(com.android.systemui.recents.model.TaskStack stack, com.android.systemui.recents.model.Task removedTask, com.android.systemui.recents.model.Task newFrontMostTask)
// Remove the view associated with this task, we can't rely on updateTransforms
// to work here because the task is no longer in the list
TaskView tv = getChildViewForTask(removedTask);
if (tv != null) {
mViewPool.returnViewToPool(tv);
}
// Notify the callback that we've removed the task and it can clean up after it
mCb.onTaskViewDismissed(removedTask);
// Get the stack scroll of the task to anchor to (since we are removing something, the front
// most task will be our anchor task)
Task anchorTask = null;
float prevAnchorTaskScroll = 0;
boolean pullStackForward = stack.getTaskCount() > 0;
if (pullStackForward) {
anchorTask = mStack.getFrontMostTask();
prevAnchorTaskScroll = mLayoutAlgorithm.getStackScrollForTask(anchorTask);
}
// Update the min/max scroll and animate other task views into their new positions
updateMinMaxScroll(true, mConfig.launchedWithAltTab, mConfig.launchedFromHome);
// Offset the stack by as much as the anchor task would otherwise move back
if (pullStackForward) {
float anchorTaskScroll = mLayoutAlgorithm.getStackScrollForTask(anchorTask);
mStackScroller.setStackScroll(mStackScroller.getStackScroll() + (anchorTaskScroll
- prevAnchorTaskScroll));
mStackScroller.boundScroll();
}
// Animate all the tasks into place
requestSynchronizeStackViewsWithModel(200);
// Update the new front most task
if (newFrontMostTask != null) {
TaskView frontTv = getChildViewForTask(newFrontMostTask);
if (frontTv != null) {
frontTv.onTaskBound(newFrontMostTask);
frontTv.fadeInActionButton(0, mConfig.taskViewEnterFromAppDuration);
}
}
// If there are no remaining tasks, then either unfilter the current stack, or just close
// the activity if there are no filtered stacks
if (mStack.getTaskCount() == 0) {
boolean shouldFinishActivity = true;
if (mStack.hasFilteredTasks()) {
mStack.unfilterTasks();
shouldFinishActivity = (mStack.getTaskCount() == 0);
}
if (shouldFinishActivity) {
mCb.onAllTaskViewsDismissed();
}
}
|
public void | onStackUnfiltered(com.android.systemui.recents.model.TaskStack newStack, java.util.ArrayList curTasks)
/*
// Calculate the current task transforms
final ArrayList<TaskViewTransform> curTaskTransforms =
getStackTransforms(curTasks, getStackScroll(), null, true);
// Update the task offsets
mLayoutAlgorithm.updateTaskOffsets(mStack.getTasks());
// Restore the stashed scroll
updateMinMaxScroll(false);
setStackScrollRaw(mStashedScroll);
boundScrollRaw();
// Compute the transforms of the items in the new stack after restoring the stashed scroll
final ArrayList<Task> tasks = mStack.getTasks();
final ArrayList<TaskViewTransform> taskTransforms =
getStackTransforms(tasks, getStackScroll(), null, true);
// Animate
mFilterAlgorithm.startFilteringAnimation(curTasks, curTaskTransforms, tasks, taskTransforms);
// Clear the saved vars
mStashedScroll = 0;
// Notify any callbacks
mCb.onTaskStackUnfilterTriggered();
*/
|
public void | onTaskViewAppIconClicked(TaskView tv)TaskViewCallbacks Implementation
if (Constants.DebugFlags.App.EnableTaskFiltering) {
if (mStack.hasFilteredTasks()) {
mStack.unfilterTasks();
} else {
mStack.filterTasks(tv.getTask());
}
}
|
public void | onTaskViewAppInfoClicked(TaskView tv)
if (mCb != null) {
mCb.onTaskViewAppInfoClicked(tv.getTask());
}
|
public void | onTaskViewClicked(TaskView tv, com.android.systemui.recents.model.Task task, boolean lockToTask)
// Cancel any doze triggers
mUIDozeTrigger.stopDozing();
if (mCb != null) {
mCb.onTaskViewClicked(this, tv, mStack, task, lockToTask);
}
|
public void | onTaskViewClipStateChanged(TaskView tv)
if (!mStackViewsDirty) {
invalidate();
}
|
public void | onTaskViewDismissed(TaskView tv)
Task task = tv.getTask();
int taskIndex = mStack.indexOfTask(task);
boolean taskWasFocused = tv.isFocusedTask();
// Announce for accessibility
tv.announceForAccessibility(getContext().getString(R.string.accessibility_recents_item_dismissed,
tv.getTask().activityLabel));
// Remove the task from the view
mStack.removeTask(task);
// If the dismissed task was focused, then we should focus the new task in the same index
if (taskWasFocused) {
ArrayList<Task> tasks = mStack.getTasks();
int nextTaskIndex = Math.min(tasks.size() - 1, taskIndex - 1);
if (nextTaskIndex >= 0) {
Task nextTask = tasks.get(nextTaskIndex);
TaskView nextTv = getChildViewForTask(nextTask);
if (nextTv != null) {
// Focus the next task, and only animate the visible state if we are launched
// from Alt-Tab
nextTv.setFocusedTask(mConfig.launchedWithAltTab);
}
}
}
|
public void | onTaskViewFocusChanged(TaskView tv, boolean focused)
if (focused) {
mFocusedTaskIndex = mStack.indexOfTask(tv.getTask());
}
|
public boolean | onTouchEvent(android.view.MotionEvent ev)
return mTouchHandler.onTouchEvent(ev);
|
void | onUserInteraction()Pokes the dozer on user interaction.
// Poke the doze trigger if it is dozing
mUIDozeTrigger.poke();
|
public void | prepareViewToEnterPool(TaskView tv)
Task task = tv.getTask();
// Clear the accessibility focus for that view
if (tv.isAccessibilityFocused()) {
tv.clearAccessibilityFocus();
}
// Report that this tasks's data is no longer being used
RecentsTaskLoader.getInstance().unloadTaskData(task);
// Detach the view from the hierarchy
detachViewFromParent(tv);
// Reset the view properties
tv.resetViewProperties();
// Reset the clip state of the task view
tv.setClipViewInStack(false);
|
public void | prepareViewToLeavePool(TaskView tv, com.android.systemui.recents.model.Task task, boolean isNewView)
// It is possible for a view to be returned to the view pool before it is laid out,
// which means that we will need to relayout the view when it is first used next.
boolean requiresRelayout = tv.getWidth() <= 0 && !isNewView;
// Rebind the task and request that this task's data be filled into the TaskView
tv.onTaskBound(task);
// Load the task data
RecentsTaskLoader.getInstance().loadTaskData(task);
// If the doze trigger has already fired, then update the state for this task view
if (mUIDozeTrigger.hasTriggered()) {
tv.setNoUserInteractionState();
}
// If we've finished the start animation, then ensure we always enable the focus animations
if (mStartEnterAnimationCompleted) {
tv.enableFocusAnimations();
}
// Find the index where this task should be placed in the stack
int insertIndex = -1;
int taskIndex = mStack.indexOfTask(task);
if (taskIndex != -1) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
Task tvTask = ((TaskView) getChildAt(i)).getTask();
if (taskIndex < mStack.indexOfTask(tvTask)) {
insertIndex = i;
break;
}
}
}
// Add/attach the view to the hierarchy
if (isNewView) {
addView(tv, insertIndex);
} else {
attachViewToParent(tv, insertIndex, tv.getLayoutParams());
if (requiresRelayout) {
tv.requestLayout();
}
}
// Set the new state for this view, including the callbacks and view clipping
tv.setCallbacks(this);
tv.setTouchEnabled(true);
tv.setClipViewInStack(true);
|
void | requestSynchronizeStackViewsWithModel()Requests that the views be synchronized with the model
requestSynchronizeStackViewsWithModel(0);
|
void | requestSynchronizeStackViewsWithModel(int duration)
if (!mStackViewsDirty) {
invalidate();
mStackViewsDirty = true;
}
if (mAwaitingFirstLayout) {
// Skip the animation if we are awaiting first layout
mStackViewsAnimationDuration = 0;
} else {
mStackViewsAnimationDuration = Math.max(mStackViewsAnimationDuration, duration);
}
|
void | requestUpdateStackViewsClip()Requests that the views clipping be updated.
if (!mStackViewsClipDirty) {
invalidate();
mStackViewsClipDirty = true;
}
|
void | reset()Resets this TaskStackView for reuse.
// Reset the focused task
resetFocusedTask();
// Return all the views to the pool
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
mViewPool.returnViewToPool(tv);
}
// Mark each task view for relayout
if (mViewPool != null) {
Iterator<TaskView> iter = mViewPool.poolViewIterator();
if (iter != null) {
while (iter.hasNext()) {
TaskView tv = iter.next();
tv.reset();
}
}
}
// Reset the stack state
mStack.reset();
mStackViewsDirty = true;
mStackViewsClipDirty = true;
mAwaitingFirstLayout = true;
mPrevAccessibilityFocusedIndex = -1;
if (mUIDozeTrigger != null) {
mUIDozeTrigger.stopDozing();
mUIDozeTrigger.resetTrigger();
}
mStackScroller.reset();
|
void | resetFocusedTask()Resets the focused task.
if ((0 <= mFocusedTaskIndex) && (mFocusedTaskIndex < mStack.getTaskCount())) {
Task t = mStack.getTasks().get(mFocusedTaskIndex);
TaskView tv = getChildViewForTask(t);
if (tv != null) {
tv.unsetFocusedTask();
}
}
mFocusedTaskIndex = -1;
|
void | setCallbacks(com.android.systemui.recents.views.TaskStackView$TaskStackViewCallbacks cb)Sets the callbacks
mCb = cb;
|
public void | setDebugOverlay(DebugOverlayView overlay)Sets the debug overlay
mDebugOverlay = overlay;
|
void | setStack(com.android.systemui.recents.model.TaskStack stack)Sets the task stack
// Set the new stack
mStack = stack;
if (mStack != null) {
mStack.setCallbacks(this);
}
// Layout again with the new stack
requestLayout();
|
public void | setStackInsetRect(android.graphics.Rect r)The stack insets to apply to the stack contents
mTaskStackBounds.set(r);
|
public void | startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx)Requests this task stacks to start it's enter-recents animation
// If we are still waiting to layout, then just defer until then
if (mAwaitingFirstLayout) {
mStartEnterAnimationRequestedAfterLayout = true;
mStartEnterAnimationContext = ctx;
return;
}
if (mStack.getTaskCount() > 0) {
// Find the launch target task
Task launchTargetTask = null;
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
if (task.isLaunchTarget) {
launchTargetTask = task;
break;
}
}
// Animate all the task views into view
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
ctx.currentTaskTransform = new TaskViewTransform();
ctx.currentStackViewIndex = i;
ctx.currentStackViewCount = childCount;
ctx.currentTaskRect = mLayoutAlgorithm.mTaskRect;
ctx.currentTaskOccludesLaunchTarget = (launchTargetTask != null) &&
launchTargetTask.group.isTaskAboveTask(task, launchTargetTask);
ctx.updateListener = mRequestUpdateClippingListener;
mLayoutAlgorithm.getStackTransform(task, mStackScroller.getStackScroll(), ctx.currentTaskTransform, null);
tv.startEnterRecentsAnimation(ctx);
}
// Add a runnable to the post animation ref counter to clear all the views
ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
@Override
public void run() {
mStartEnterAnimationCompleted = true;
// Poke the dozer to restart the trigger after the animation completes
mUIDozeTrigger.poke();
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
SystemServicesProxy ssp = loader.getSystemServicesProxy();
int childCount = getChildCount();
if (childCount > 0) {
// Focus the first view if accessibility is enabled
if (ssp.isTouchExplorationEnabled()) {
TaskView tv = ((TaskView) getChildAt(childCount - 1));
tv.requestAccessibilityFocus();
mPrevAccessibilityFocusedIndex = mStack.indexOfTask(tv.getTask());
}
}
// Start the focus animation when alt-tabbing
if (mConfig.launchedWithAltTab && !mConfig.launchedHasConfigurationChanged) {
View tv = getChildAt(mFocusedTaskIndex);
if (tv != null) {
((TaskView) tv).setFocusedTask(true);
}
}
}
});
}
|
public void | startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx)Requests this task stacks to start it's exit-recents animation.
// Stop any scrolling
mStackScroller.stopScroller();
mStackScroller.stopBoundScrollAnimation();
// Animate all the task views out of view
ctx.offscreenTranslationY = mLayoutAlgorithm.mViewRect.bottom -
(mLayoutAlgorithm.mTaskRect.top - mLayoutAlgorithm.mViewRect.top);
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView tv = (TaskView) getChildAt(i);
tv.startExitToHomeAnimation(ctx);
}
|
public void | startLaunchTaskAnimation(TaskView tv, java.lang.Runnable r, boolean lockToTask)Animates a task view in this stack as it launches.
Task launchTargetTask = tv.getTask();
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
TaskView t = (TaskView) getChildAt(i);
if (t == tv) {
t.setClipViewInStack(false);
t.startLaunchTaskAnimation(r, true, true, lockToTask);
} else {
boolean occludesLaunchTarget = launchTargetTask.group.isTaskAboveTask(t.getTask(),
launchTargetTask);
t.startLaunchTaskAnimation(null, false, occludesLaunchTarget, lockToTask);
}
}
|
boolean | synchronizeStackViewsWithModel()Synchronizes the views with the model
if (mStackViewsDirty) {
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
SystemServicesProxy ssp = loader.getSystemServicesProxy();
// Get all the task transforms
ArrayList<Task> tasks = mStack.getTasks();
float stackScroll = mStackScroller.getStackScroll();
int[] visibleRange = mTmpVisibleRange;
boolean isValidVisibleRange = updateStackTransforms(mCurrentTaskTransforms, tasks,
stackScroll, visibleRange, false);
if (mDebugOverlay != null) {
mDebugOverlay.setText("vis[" + visibleRange[1] + "-" + visibleRange[0] + "]");
}
// Return all the invisible children to the pool
mTmpTaskViewMap.clear();
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
Task task = tv.getTask();
int taskIndex = mStack.indexOfTask(task);
if (visibleRange[1] <= taskIndex && taskIndex <= visibleRange[0]) {
mTmpTaskViewMap.put(task, tv);
} else {
mViewPool.returnViewToPool(tv);
}
}
// Pick up all the newly visible children and update all the existing children
for (int i = visibleRange[0]; isValidVisibleRange && i >= visibleRange[1]; i--) {
Task task = tasks.get(i);
TaskViewTransform transform = mCurrentTaskTransforms.get(i);
TaskView tv = mTmpTaskViewMap.get(task);
int taskIndex = mStack.indexOfTask(task);
if (tv == null) {
tv = mViewPool.pickUpViewFromPool(task, task);
if (mStackViewsAnimationDuration > 0) {
// For items in the list, put them in start animating them from the
// approriate ends of the list where they are expected to appear
if (Float.compare(transform.p, 0f) <= 0) {
mLayoutAlgorithm.getStackTransform(0f, 0f, mTmpTransform, null);
} else {
mLayoutAlgorithm.getStackTransform(1f, 0f, mTmpTransform, null);
}
tv.updateViewPropertiesToTaskTransform(mTmpTransform, 0);
}
}
// Animate the task into place
tv.updateViewPropertiesToTaskTransform(mCurrentTaskTransforms.get(taskIndex),
mStackViewsAnimationDuration, mRequestUpdateClippingListener);
// Request accessibility focus on the next view if we removed the task
// that previously held accessibility focus
childCount = getChildCount();
if (childCount > 0 && ssp.isTouchExplorationEnabled()) {
TaskView atv = (TaskView) getChildAt(childCount - 1);
int indexOfTask = mStack.indexOfTask(atv.getTask());
if (mPrevAccessibilityFocusedIndex != indexOfTask) {
tv.requestAccessibilityFocus();
mPrevAccessibilityFocusedIndex = indexOfTask;
}
}
}
// Reset the request-synchronize params
mStackViewsAnimationDuration = 0;
mStackViewsDirty = false;
mStackViewsClipDirty = true;
return true;
}
return false;
|
void | updateMinMaxScroll(boolean boundScrollToNewMinMax, boolean launchedWithAltTab, boolean launchedFromHome)Updates the min and max virtual scroll bounds
// Compute the min and max scroll values
mLayoutAlgorithm.computeMinMaxScroll(mStack.getTasks(), launchedWithAltTab, launchedFromHome);
// Debug logging
if (boundScrollToNewMinMax) {
mStackScroller.boundScroll();
}
|
public void | updateMinMaxScrollForStack(com.android.systemui.recents.model.TaskStack stack, boolean launchedWithAltTab, boolean launchedFromHome)This is ONLY used from AlternateRecentsComponent to update the dummy stack view for purposes
of getting the task rect to animate to.
mStack = stack;
updateMinMaxScroll(false, launchedWithAltTab, launchedFromHome);
|
private boolean | updateStackTransforms(java.util.ArrayList taskTransforms, java.util.ArrayList tasks, float stackScroll, int[] visibleRangeOut, boolean boundTranslationsToRect)Gets the stack transforms of a list of tasks, and returns the visible range of tasks.
int taskTransformCount = taskTransforms.size();
int taskCount = tasks.size();
int frontMostVisibleIndex = -1;
int backMostVisibleIndex = -1;
// We can reuse the task transforms where possible to reduce object allocation
if (taskTransformCount < taskCount) {
// If there are less transforms than tasks, then add as many transforms as necessary
for (int i = taskTransformCount; i < taskCount; i++) {
taskTransforms.add(new TaskViewTransform());
}
} else if (taskTransformCount > taskCount) {
// If there are more transforms than tasks, then just subset the transform list
taskTransforms.subList(0, taskCount);
}
// Update the stack transforms
TaskViewTransform prevTransform = null;
for (int i = taskCount - 1; i >= 0; i--) {
TaskViewTransform transform = mLayoutAlgorithm.getStackTransform(tasks.get(i),
stackScroll, taskTransforms.get(i), prevTransform);
if (transform.visible) {
if (frontMostVisibleIndex < 0) {
frontMostVisibleIndex = i;
}
backMostVisibleIndex = i;
} else {
if (backMostVisibleIndex != -1) {
// We've reached the end of the visible range, so going down the rest of the
// stack, we can just reset the transforms accordingly
while (i >= 0) {
taskTransforms.get(i).reset();
i--;
}
break;
}
}
if (boundTranslationsToRect) {
transform.translationY = Math.min(transform.translationY,
mLayoutAlgorithm.mViewRect.bottom);
}
prevTransform = transform;
}
if (visibleRangeOut != null) {
visibleRangeOut[0] = frontMostVisibleIndex;
visibleRangeOut[1] = backMostVisibleIndex;
}
return frontMostVisibleIndex != -1 && backMostVisibleIndex != -1;
|