Merge "Don't reload the layout every time we enter Recents. (Bug 18160176)" into lmp-mr1-dev

This commit is contained in:
Winson Chung
2014-11-06 19:20:55 +00:00
committed by Android (Google) Code Review
10 changed files with 269 additions and 89 deletions

View File

@@ -54,7 +54,7 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
/** A proxy implementation for the recents component */
public class AlternateRecentsComponent {
public class AlternateRecentsComponent implements ActivityOptions.OnAnimationStartedListener {
final public static String EXTRA_FROM_HOME = "recents.triggeredOverHome";
final public static String EXTRA_FROM_SEARCH_HOME = "recents.triggeredOverSearchHome";
@@ -62,7 +62,9 @@ public class AlternateRecentsComponent {
final public static String EXTRA_FROM_TASK_ID = "recents.activeTaskId";
final public static String EXTRA_TRIGGERED_FROM_ALT_TAB = "recents.triggeredFromAltTab";
final public static String EXTRA_TRIGGERED_FROM_HOME_KEY = "recents.triggeredFromHomeKey";
final public static String EXTRA_REUSE_TASK_STACK_VIEWS = "recents.reuseTaskStackViews";
final public static String ACTION_START_ENTER_ANIMATION = "action_start_enter_animation";
final public static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
final public static String ACTION_HIDE_RECENTS_ACTIVITY = "action_hide_recents_activity";
@@ -77,7 +79,10 @@ public class AlternateRecentsComponent {
Context mContext;
LayoutInflater mInflater;
SystemServicesProxy mSystemServicesProxy;
Handler mHandler;
boolean mBootCompleted;
boolean mStartAnimationTriggered;
boolean mCanReuseTaskStackViews = true;
// Task launching
RecentsConfiguration mConfig;
@@ -103,6 +108,7 @@ public class AlternateRecentsComponent {
mInflater = LayoutInflater.from(context);
mContext = context;
mSystemServicesProxy = new SystemServicesProxy(context);
mHandler = new Handler();
mTaskStackBounds = new Rect();
}
@@ -128,7 +134,7 @@ public class AlternateRecentsComponent {
}
// When we start, preload the metadata associated with the previous tasks
RecentsTaskLoader.getInstance().preload(mContext);
RecentsTaskLoader.getInstance().preload(mContext, RecentsTaskLoader.ALL_TASKS);
}
public void onBootCompleted() {
@@ -176,7 +182,9 @@ public class AlternateRecentsComponent {
}
public void onPreloadRecents() {
// Do nothing
// When we start, preload the metadata associated with the previous tasks
RecentsTaskLoader.getInstance().preload(mContext,
Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
}
public void onCancelPreloadingRecents() {
@@ -186,7 +194,7 @@ public class AlternateRecentsComponent {
void showRelativeAffiliatedTask(boolean showNextTask) {
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
-1, -1, false, true, null, null);
-1, -1, RecentsTaskLoader.ALL_TASKS, false, true, null, null);
// Return early if there are no tasks
if (stack.getTaskCount() == 0) return;
@@ -251,6 +259,8 @@ public class AlternateRecentsComponent {
}
public void onConfigurationChanged(Configuration newConfig) {
// Don't reuse task stack views if the configuration changes
mCanReuseTaskStackViews = false;
// Reload the header bar layout
reloadHeaderBarLayout();
}
@@ -364,23 +374,28 @@ public class AlternateRecentsComponent {
* Creates the activity options for a unknown state->recents transition.
*/
ActivityOptions getUnknownTransitionActivityOptions() {
mStartAnimationTriggered = false;
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_unknown_enter,
R.anim.recents_from_unknown_exit);
R.anim.recents_from_unknown_exit,
mHandler, this);
}
/**
* Creates the activity options for a home->recents transition.
*/
ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) {
mStartAnimationTriggered = false;
if (fromSearchHome) {
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_search_launcher_enter,
R.anim.recents_from_search_launcher_exit);
R.anim.recents_from_search_launcher_exit,
mHandler, this);
}
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_launcher_enter,
R.anim.recents_from_launcher_exit);
R.anim.recents_from_launcher_exit,
mHandler, this);
}
/**
@@ -408,9 +423,10 @@ public class AlternateRecentsComponent {
c.setBitmap(null);
}
mStartAnimationTriggered = false;
return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mStatusBarView,
thumbnail, toTaskRect.left, toTaskRect.top, toTaskRect.width(),
toTaskRect.height(), null);
toTaskRect.height(), this);
}
// If both the screenshot and thumbnail fails, then just fall back to the default transition
@@ -423,7 +439,7 @@ public class AlternateRecentsComponent {
// Get the stack of tasks that we are animating into
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
TaskStack stack = loader.getTaskStack(mSystemServicesProxy, mContext.getResources(),
runningTaskId, -1, false, isTopTaskHome, null, null);
runningTaskId, -1, RecentsTaskLoader.ALL_TASKS, false, isTopTaskHome, null, null);
if (stack.getTaskCount() == 0) {
return null;
}
@@ -529,11 +545,13 @@ public class AlternateRecentsComponent {
}
intent.putExtra(EXTRA_TRIGGERED_FROM_ALT_TAB, mTriggeredFromAltTab);
intent.putExtra(EXTRA_FROM_TASK_ID, (topTask != null) ? topTask.id : -1);
intent.putExtra(EXTRA_REUSE_TASK_STACK_VIEWS, mCanReuseTaskStackViews);
if (opts != null) {
mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
} else {
mContext.startActivityAsUser(intent, UserHandle.CURRENT);
}
mCanReuseTaskStackViews = true;
}
/** Sets the RecentsComponent callbacks. */
@@ -547,4 +565,42 @@ public class AlternateRecentsComponent {
sRecentsComponentCallbacks.onVisibilityChanged(visible);
}
}
/**** OnAnimationStartedListener Implementation ****/
@Override
public void onAnimationStarted() {
// Notify recents to start the enter animation
if (!mStartAnimationTriggered) {
// There can be a race condition between the start animation callback and
// the start of the new activity (where we register the receiver that listens
// to this broadcast, so we add our own receiver and if that gets called, then
// we know the activity has not yet started and we can retry sending the broadcast.
BroadcastReceiver fallbackReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (getResultCode() == Activity.RESULT_OK) {
mStartAnimationTriggered = true;
return;
}
// Schedule for the broadcast to be sent again after some time
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
onAnimationStarted();
}
}, 25);
}
};
// Send the broadcast to notify Recents that the animation has started
Intent intent = new Intent(ACTION_START_ENTER_ANIMATION);
intent.setPackage(mContext.getPackageName());
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT |
Intent.FLAG_RECEIVER_FOREGROUND);
mContext.sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,
fallbackReceiver, null, Activity.RESULT_CANCELED, null, null);
}
}
}

View File

@@ -27,6 +27,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -142,6 +143,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
} else if (action.equals(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
// If we are toggling Recents, then first unfilter any filtered stacks first
dismissRecentsToFocusedTaskOrHome(true);
} else if (action.equals(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION)) {
// Trigger the enter animation
onEnterAnimationTriggered();
// Notify the fallback receiver that we have successfully got the broadcast
// See AlternateRecentsComponent.onAnimationStarted()
setResultCode(Activity.RESULT_OK);
}
}
};
@@ -157,7 +164,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// When the screen turns off, dismiss Recents to Home
dismissRecentsToHome(false);
// Start preloading some tasks in the background
RecentsTaskLoader.getInstance().preload(RecentsActivity.this);
RecentsTaskLoader.getInstance().preload(RecentsActivity.this,
Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
} else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
// When the search activity changes, update the Search widget
refreshSearchWidget();
@@ -188,6 +196,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
AlternateRecentsComponent.EXTRA_FROM_TASK_ID, -1);
mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
mConfig.launchedReuseTaskStackViews = launchIntent.getBooleanExtra(
AlternateRecentsComponent.EXTRA_REUSE_TASK_STACK_VIEWS, false);
// Load all the tasks
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
@@ -397,8 +407,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Update if we are getting a configuration change
if (savedInstanceState != null) {
// Update RecentsConfiguration
mConfig = RecentsConfiguration.reinitialize(this,
RecentsTaskLoader.getInstance().getSystemServicesProxy());
mConfig.updateOnConfigurationChange();
onConfigurationChange();
// Trigger the enter animation
onEnterAnimationTriggered();
}
// Start listening for widget package changes if there is one bound, post it since we don't
@@ -428,19 +442,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
/** Called when the configuration changes. */
void onConfigurationChange() {
// Update RecentsConfiguration
mConfig = RecentsConfiguration.reinitialize(this,
RecentsTaskLoader.getInstance().getSystemServicesProxy());
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
// Animate the SystemUI scrim views
mScrimViews.startEnterRecentsAnimation();
}
/** Handles changes to the activity visibility. */
void onRecentsActivityVisibilityChanged(boolean visible) {
if (!visible) {
@@ -474,6 +475,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
IntentFilter filter = new IntentFilter();
filter.addAction(AlternateRecentsComponent.ACTION_HIDE_RECENTS_ACTIVITY);
filter.addAction(AlternateRecentsComponent.ACTION_TOGGLE_RECENTS_ACTIVITY);
filter.addAction(AlternateRecentsComponent.ACTION_START_ENTER_ANIMATION);
registerReceiver(mServiceBroadcastReceiver, filter);
// Register any broadcast receivers for the task loader
@@ -492,8 +494,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
protected void onStop() {
super.onStop();
// Remove all the views
mRecentsView.removeAllTaskStacks();
// Notify the views that we are no longer visible
mRecentsView.onRecentsHidden();
// Unregister the RecentsService receiver
unregisterReceiver(mServiceBroadcastReceiver);
@@ -515,8 +517,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
}
@Override
public void onEnterAnimationComplete() {
public void onEnterAnimationTriggered() {
// Try and start the enter animation (or restart it on configuration changed)
ReferenceCountedTrigger t = new ReferenceCountedTrigger(this, null, null, null);
mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(t));
@@ -584,7 +585,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
/** Called when debug mode is triggered */
public void onDebugModeTriggered() {
if (mConfig.developerOptionsEnabled) {
SharedPreferences settings = getSharedPreferences(getPackageName(), 0);
if (settings.getBoolean(Constants.Values.App.Key_DebugModeEnabled, false)) {

View File

@@ -115,8 +115,8 @@ public class RecentsConfiguration {
public boolean launchedWithAltTab;
public boolean launchedWithNoRecentTasks;
public boolean launchedFromAppWithThumbnail;
public boolean launchedFromAppWithScreenshot;
public boolean launchedFromHome;
public boolean launchedReuseTaskStackViews;
public int launchedToTaskId;
/** Misc **/
@@ -308,6 +308,7 @@ public class RecentsConfiguration {
launchedWithNoRecentTasks = false;
launchedFromAppWithThumbnail = false;
launchedFromHome = false;
launchedReuseTaskStackViews = false;
launchedToTaskId = -1;
}

View File

@@ -82,4 +82,9 @@ public class DozeTrigger {
public boolean hasTriggered() {
return mHasTriggered;
}
/** Resets the doze trigger state. */
public void resetTrigger() {
mHasTriggered = false;
}
}

View File

@@ -260,6 +260,7 @@ public class RecentsTaskLoader {
private static final String TAG = "RecentsTaskLoader";
static RecentsTaskLoader sInstance;
public static final int ALL_TASKS = -1;
SystemServicesProxy mSystemServicesProxy;
DrawableLruCache mApplicationIconCache;
@@ -326,10 +327,9 @@ public class RecentsTaskLoader {
/** Gets the list of recent tasks, ordered from back to front. */
private static List<ActivityManager.RecentTaskInfo> getRecentTasks(SystemServicesProxy ssp,
boolean isTopTaskHome) {
RecentsConfiguration config = RecentsConfiguration.getInstance();
int numTasksToLoad, boolean isTopTaskHome) {
List<ActivityManager.RecentTaskInfo> tasks =
ssp.getRecentTasks(config.maxNumTasksToLoad, UserHandle.CURRENT.getIdentifier(),
ssp.getRecentTasks(numTasksToLoad, UserHandle.CURRENT.getIdentifier(),
isTopTaskHome);
Collections.reverse(tasks);
return tasks;
@@ -416,7 +416,8 @@ public class RecentsTaskLoader {
ArrayList<Task.TaskKey> taskKeys = new ArrayList<Task.TaskKey>();
ArrayList<Task> tasksToLoad = new ArrayList<Task>();
TaskStack stack = getTaskStack(mSystemServicesProxy, context.getResources(),
-1, preloadCount, true, isTopTaskHome, taskKeys, tasksToLoad);
-1, preloadCount, RecentsTaskLoader.ALL_TASKS, true, isTopTaskHome, taskKeys,
tasksToLoad);
SpaceNode root = new SpaceNode();
root.setStack(stack);
@@ -428,10 +429,10 @@ public class RecentsTaskLoader {
}
/** Preloads the set of recent tasks (not including thumbnails). */
public void preload(Context context) {
public void preload(Context context, int numTasksToPreload) {
ArrayList<Task> tasksToLoad = new ArrayList<Task>();
getTaskStack(mSystemServicesProxy, context.getResources(),
-1, -1, true, true, null, tasksToLoad);
-1, -1, numTasksToPreload, true, true, null, tasksToLoad);
// Start the task loader and add all the tasks we need to load
mLoadQueue.addTasks(tasksToLoad);
@@ -440,11 +441,13 @@ public class RecentsTaskLoader {
/** Creates a lightweight stack of the current recent tasks, without thumbnails and icons. */
public synchronized TaskStack getTaskStack(SystemServicesProxy ssp, Resources res,
int preloadTaskId, int preloadTaskCount,
int preloadTaskId, int preloadTaskCount, int loadTaskCount,
boolean loadTaskThumbnails, boolean isTopTaskHome,
List<Task.TaskKey> taskKeysOut, List<Task> tasksToLoadOut) {
RecentsConfiguration config = RecentsConfiguration.getInstance();
List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp, isTopTaskHome);
List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(ssp,
(loadTaskCount == ALL_TASKS ? config.maxNumTasksToLoad : loadTaskCount),
isTopTaskHome);
HashMap<Task.ComponentNameKey, ActivityInfoHandle> activityInfoCache =
new HashMap<Task.ComponentNameKey, ActivityInfoHandle>();
ArrayList<Task> tasksToAdd = new ArrayList<Task>();

View File

@@ -95,42 +95,57 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** Set/get the bsp root node */
public void setTaskStacks(ArrayList<TaskStack> stacks) {
// Remove all TaskStackViews (but leave the search bar)
int numStacks = stacks.size();
// Make a list of the stack view children only
ArrayList<TaskStackView> stackViews = new ArrayList<TaskStackView>();
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
View v = getChildAt(i);
if (v != mSearchBar) {
removeViewAt(i);
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child != mSearchBar) {
stackViews.add((TaskStackView) child);
}
}
// Create and add all the stacks for this partition of space.
// Remove all/extra stack views
int numTaskStacksToKeep = 0; // Keep no tasks if we are recreating the layout
if (mConfig.launchedReuseTaskStackViews) {
numTaskStacksToKeep = Math.min(childCount, numStacks);
}
for (int i = stackViews.size() - 1; i >= numTaskStacksToKeep; i--) {
removeView(stackViews.get(i));
stackViews.remove(i);
}
// Update the stack views that we are keeping
for (int i = 0; i < numTaskStacksToKeep; i++) {
stackViews.get(i).setStack(stacks.get(i));
}
// Add remaining/recreate stack views
mStacks = stacks;
int numStacks = mStacks.size();
for (int i = 0; i < numStacks; i++) {
TaskStack stack = mStacks.get(i);
for (int i = stackViews.size(); i < numStacks; i++) {
TaskStack stack = stacks.get(i);
TaskStackView stackView = new TaskStackView(getContext(), stack);
stackView.setCallbacks(this);
// Enable debug mode drawing
if (mConfig.debugModeEnabled) {
stackView.setDebugOverlay(mDebugOverlay);
}
addView(stackView);
}
// Enable debug mode drawing on all the stacks if necessary
if (mConfig.debugModeEnabled) {
for (int i = childCount - 1; i >= 0; i--) {
View v = getChildAt(i);
if (v != mSearchBar) {
TaskStackView stackView = (TaskStackView) v;
stackView.setDebugOverlay(mDebugOverlay);
}
}
}
// Reset the launched state
mAlreadyLaunchingTask = false;
}
/** Removes all the task stack views from this recents view. */
public void removeAllTaskStacks() {
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
View child = getChildAt(i);
if (child != mSearchBar) {
removeViewAt(i);
}
}
// Trigger a new layout
requestLayout();
}
/** Launches the focused task from the first stack if possible */
@@ -529,6 +544,19 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
mCb.onAllTaskViewsDismissed();
}
/** Final callback after Recents is finally hidden. */
public void onRecentsHidden() {
// Notify each task stack view
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child != mSearchBar) {
TaskStackView stackView = (TaskStackView) child;
stackView.onRecentsHidden();
}
}
}
@Override
public void onTaskStackFilterTriggered() {
// Hide the search bar

View File

@@ -40,6 +40,7 @@ import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
/* The visual representation of a task stack view */
@@ -99,25 +100,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
};
// A convenience runnable to return all views to the pool
Runnable mReturnAllViewsToPoolRunnable = new Runnable() {
@Override
public void run() {
int childCount = getChildCount();
for (int i = childCount - 1; i >= 0; i--) {
TaskView tv = (TaskView) getChildAt(i);
mViewPool.returnViewToPool(tv);
// Also hide the view since we don't need it anymore
tv.setVisibility(View.INVISIBLE);
}
}
};
public TaskStackView(Context context, TaskStack stack) {
super(context);
// Set the stack first
setStack(stack);
mConfig = RecentsConfiguration.getInstance();
mStack = stack;
mStack.setCallbacks(this);
mViewPool = new ViewPool<TaskView, Task>(context, this);
mInflater = LayoutInflater.from(context);
mLayoutAlgorithm = new TaskStackViewLayoutAlgorithm(mConfig);
@@ -143,11 +130,62 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mCb = cb;
}
/** Sets the task stack */
void setStack(TaskStack stack) {
// Unset the old stack
if (mStack != null) {
mStack.setCallbacks(null);
// Return all existing views to the pool
reset();
// Layout again with the new stack
requestLayout();
}
// Set the new stack
mStack = stack;
if (mStack != null) {
mStack.setCallbacks(this);
}
}
/** Sets the debug overlay */
public void setDebugOverlay(DebugOverlayView overlay) {
mDebugOverlay = overlay;
}
/** Resets this TaskStackView for reuse. */
void reset() {
// 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
resetFocusedTask();
mStackViewsDirty = true;
mStackViewsClipDirty = true;
mAwaitingFirstLayout = true;
mPrevAccessibilityFocusedIndex = -1;
if (mUIDozeTrigger != null) {
mUIDozeTrigger.stopDozing();
mUIDozeTrigger.resetTrigger();
}
}
/** Requests that the views be synchronized with the model */
void requestSynchronizeStackViewsWithModel() {
requestSynchronizeStackViewsWithModel(0);
@@ -510,6 +548,16 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
tv.dismissTask();
}
/** Resets the focused task. */
void resetFocusedTask() {
if (mFocusedTaskIndex > -1) {
Task t = mStack.getTasks().get(mFocusedTaskIndex);
TaskView tv = getChildViewForTask(t);
tv.unsetFocusedTask();
}
mFocusedTaskIndex = -1;
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
@@ -543,6 +591,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
@Override
public void computeScroll() {
if (mStack == null) return;
mStackScroller.computeScroll();
// Synchronize the views
synchronizeStackViewsWithModel();
@@ -758,9 +808,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView tv = (TaskView) getChildAt(i);
tv.startExitToHomeAnimation(ctx);
}
// Add a runnable to the post animation ref counter to clear all the views
ctx.postAnimationTrigger.addLastDecrementRunnable(mReturnAllViewsToPoolRunnable);
}
/** Animates a task view in this stack as it launches. */
@@ -780,6 +827,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
/** Final callback after Recents is finally hidden. */
void onRecentsHidden() {
reset();
setStack(null);
}
public boolean isTransformedTouchPointInView(float x, float y, View child) {
return isTransformedTouchPointInView(x, y, child, null);
}
@@ -944,20 +997,23 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Reset the view properties
tv.resetViewProperties();
// Reset the clip state of the task view
tv.setClipViewInStack(false);
}
@Override
public void prepareViewToLeavePool(TaskView tv, 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);
// Sanity check, the task view should always be clipping against the stack at this point,
// but just in case, re-enable it here
tv.setClipViewInStack(true);
// If the doze trigger has already fired, then update the state for this task view
if (mUIDozeTrigger.hasTriggered()) {
tv.setNoUserInteractionState();
@@ -985,13 +1041,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Add/attach the view to the hierarchy
if (isNewView) {
addView(tv, insertIndex);
// Set the callbacks and listeners for this new view
tv.setTouchEnabled(true);
tv.setCallbacks(this);
} 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);
}
@Override

View File

@@ -112,6 +112,14 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mCb = cb;
}
/** Resets this TaskView for reuse. */
void reset() {
resetViewProperties();
resetNoUserInteractionState();
setClipViewInStack(false);
setCallbacks(null);
}
/** Gets the task */
Task getTask() {
return mTask;
@@ -191,6 +199,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Resets this view's properties */
void resetViewProperties() {
setDim(0);
setLayerType(View.LAYER_TYPE_NONE, null);
TaskViewTransform.reset(this);
}
@@ -448,6 +457,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mHeaderView.setNoUserInteractionState();
}
/** Resets the state tracking that the user has not interacted with the stack after a certain time. */
void resetNoUserInteractionState() {
mHeaderView.resetNoUserInteractionState();
}
/** Dismisses this task. */
void dismissTask() {
// Animate out the view and call the callback

View File

@@ -263,6 +263,11 @@ public class TaskViewHeader extends FrameLayout {
}
}
/** Resets the state tracking that the user has not interacted with the stack after a certain time. */
void resetNoUserInteractionState() {
mDismissButton.setVisibility(View.INVISIBLE);
}
@Override
protected int[] onCreateDrawableState(int extraSpace) {

View File

@@ -75,4 +75,12 @@ public class ViewPool<V, T> {
mViewCreator.prepareViewToLeavePool(v, prepareData, isNewView);
return v;
}
/** Returns an iterator to the list of the views in the pool. */
Iterator<V> poolViewIterator() {
if (mPool != null) {
return mPool.iterator();
}
return null;
}
}