Moving resources out of ResourceConfiguration.

- We can no longer make assumptions about the ability to
  get resources for the RecentsActivity before the activity
  is launched (the configuration of the launched activity
  can differ than the current configuration if a window
  is docked).  As such, we reduce RecentsConfiguration
  to the set of values that are context agnostic, or can
  be calculated directly given an application context.
  This ensures that we will continue to be able to compute
  the target task bounds given any context.

Change-Id: I423c90635eb294aa2d78a6f56771b98ee2b9d5e4
This commit is contained in:
Winson
2015-09-28 11:24:36 -07:00
parent b4a6d9847b
commit 35f3050959
28 changed files with 552 additions and 494 deletions

View File

@@ -19,9 +19,6 @@
<!-- thickness (width) of the navigation bar on phones that require it -->
<dimen name="navigation_bar_size">@*android:dimen/navigation_bar_width</dimen>
<!-- The side padding for the task stack as a percentage of the width. -->
<item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.26</item>
<!-- Standard notification width + gravity -->
<dimen name="notification_panel_width">@dimen/standard_notification_panel_width</dimen>
<integer name="notification_panel_layout_gravity">@integer/standard_notification_panel_layout_gravity</integer>

View File

@@ -16,10 +16,6 @@
*/
-->
<resources>
<!-- Recent Applications parameters -->
<!-- The side padding for the task stack as a percentage of the width. -->
<item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.25</item>
<fraction name="keyguard_clock_y_fraction_max">37%</fraction>
<fraction name="keyguard_clock_y_fraction_min">20%</fraction>

View File

@@ -32,9 +32,4 @@
<!-- Set to true to enable the user switcher on the keyguard. -->
<bool name="config_keyguardUserSwitcher">true</bool>
<!-- Transposes the search bar layout in landscape. -->
<bool name="recents_has_transposed_search_bar">true</bool>
<!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
<bool name="recents_has_transposed_nav_bar">false</bool>
</resources>

View File

@@ -39,12 +39,6 @@
<!-- On tablets this is just the close_handle_height -->
<dimen name="peek_height">@dimen/close_handle_height</dimen>
<!-- The side padding for the task stack as a percentage of the width. -->
<item name="recents_stack_width_padding_percentage" format="float" type="dimen">0.075</item>
<!-- The height of the search bar space. -->
<dimen name="recents_search_bar_space_height">72dp</dimen>
<!-- The fraction of the screen height where the clock on the Keyguard has its center. The
max value is used when no notifications are displaying, and the min value is when the
highest possible number of notifications are showing. -->

View File

@@ -25,10 +25,5 @@
<!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
card. -->
<integer name="keyguard_max_notification_count">5</integer>
<!-- Transposes the search bar layout in landscape. -->
<bool name="recents_has_transposed_search_bar">false</bool>
<!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
<bool name="recents_has_transposed_nav_bar">false</bool>
</resources>

View File

@@ -189,12 +189,6 @@
<!-- The delay to enforce between each alt-tab key press. -->
<integer name="recents_alt_tab_key_delay">200</integer>
<!-- Transposes the search bar layout in landscape. -->
<bool name="recents_has_transposed_search_bar">true</bool>
<!-- Transposes the nav bar in landscape (only used for purposes of layout). -->
<bool name="recents_has_transposed_nav_bar">true</bool>
<!-- Svelte specific logic, see RecentsConfiguration.SVELTE_* constants. -->
<integer name="recents_svelte_level">0</integer>

View File

@@ -38,7 +38,6 @@ import android.util.MutableBoolean;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Prefs;
import com.android.systemui.R;
@@ -500,9 +499,8 @@ public class Recents extends SystemUI
mStatusBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
mNavBarHeight = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_height);
mNavBarWidth = res.getDimensionPixelSize(com.android.internal.R.dimen.navigation_bar_width);
// TODO: We can't rely on this anymore since the activity context will yield different
// resources while multiwindow is enabled
mConfig = RecentsConfiguration.reinitialize(mContext, mSystemServicesProxy);
mConfig = RecentsConfiguration.initialize(mContext, mSystemServicesProxy);
mConfig.update(mContext, mSystemServicesProxy, mSystemServicesProxy.getWindowRect());
mConfig.updateOnConfigurationChange();
Rect searchBarBounds = new Rect();
// Try and pre-emptively bind the search widget on startup to ensure that we
@@ -515,7 +513,7 @@ public class Recents extends SystemUI
mConfig.getAvailableTaskStackBounds(windowRect,
mStatusBarHeight, (mConfig.hasTransposedNavBar ? mNavBarWidth : 0), searchBarBounds,
mTaskStackBounds);
if (mConfig.isLandscape && mConfig.hasTransposedNavBar) {
if (mConfig.hasTransposedNavBar) {
mSystemInsets.set(0, mStatusBarHeight, mNavBarWidth, 0);
} else {
mSystemInsets.set(0, mStatusBarHeight, 0, mNavBarHeight);
@@ -740,7 +738,7 @@ public class Recents extends SystemUI
// Don't reinitialize the configuration completely here, since it has the wrong context,
// only update the parts that we can get from any context
RecentsConfiguration config = RecentsConfiguration.getInstance();
config.reinitializeWithApplicationContext(mContext, mSystemServicesProxy);
config.update(mContext, mSystemServicesProxy, mSystemServicesProxy.getWindowRect());
if (sInstanceLoadPlan == null) {
// Create a new load plan if onPreloadRecents() was never triggered
@@ -816,15 +814,16 @@ public class Recents extends SystemUI
ActivityOptions opts, boolean fromHome, boolean fromSearchHome, boolean fromThumbnail,
TaskStackViewLayoutAlgorithm.VisibilityReport vr) {
// Update the configuration based on the launch options
mConfig.launchedFromHome = fromSearchHome || fromHome;
mConfig.launchedFromSearchHome = fromSearchHome;
mConfig.launchedFromAppWithThumbnail = fromThumbnail;
mConfig.launchedToTaskId = (topTask != null) ? topTask.id : -1;
mConfig.launchedWithAltTab = mTriggeredFromAltTab;
mConfig.launchedReuseTaskStackViews = mCanReuseTaskStackViews;
mConfig.launchedNumVisibleTasks = vr.numVisibleTasks;
mConfig.launchedNumVisibleThumbnails = vr.numVisibleThumbnails;
mConfig.launchedHasConfigurationChanged = false;
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
launchState.launchedFromHome = fromSearchHome || fromHome;
launchState.launchedFromSearchHome = fromSearchHome;
launchState.launchedFromAppWithThumbnail = fromThumbnail;
launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
launchState.launchedWithAltTab = mTriggeredFromAltTab;
launchState.launchedReuseTaskStackViews = mCanReuseTaskStackViews;
launchState.launchedNumVisibleTasks = vr.numVisibleTasks;
launchState.launchedNumVisibleThumbnails = vr.numVisibleThumbnails;
launchState.launchedHasConfigurationChanged = false;
Intent intent = new Intent(sToggleRecentsAction);
intent.setClassName(sRecentsPackage, sRecentsActivity);

View File

@@ -25,17 +25,13 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.SystemClock;
import android.os.UserHandle;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewStub;
import android.widget.Toast;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
@@ -182,18 +178,19 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
// Start loading tasks according to the load plan
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
if (!plan.hasTasks()) {
loader.preloadTasks(plan, mConfig.launchedFromHome);
loader.preloadTasks(plan, launchState.launchedFromHome);
}
RecentsTaskLoadPlan.Options loadOpts = new RecentsTaskLoadPlan.Options();
loadOpts.runningTaskId = mConfig.launchedToTaskId;
loadOpts.numVisibleTasks = mConfig.launchedNumVisibleTasks;
loadOpts.numVisibleTaskThumbnails = mConfig.launchedNumVisibleThumbnails;
loadOpts.runningTaskId = launchState.launchedToTaskId;
loadOpts.numVisibleTasks = launchState.launchedNumVisibleTasks;
loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
loader.loadTasks(this, plan, loadOpts);
TaskStack stack = plan.getTaskStack();
mConfig.launchedWithNoRecentTasks = !plan.hasTasks();
if (!mConfig.launchedWithNoRecentTasks) {
launchState.launchedWithNoRecentTasks = !plan.hasTasks();
if (!launchState.launchedWithNoRecentTasks) {
mRecentsView.setTaskStack(stack);
}
@@ -204,19 +201,19 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent,
ActivityOptions.makeCustomAnimation(this,
mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_enter :
launchState.launchedFromSearchHome ? R.anim.recents_to_search_launcher_enter :
R.anim.recents_to_launcher_enter,
mConfig.launchedFromSearchHome ? R.anim.recents_to_search_launcher_exit :
launchState.launchedFromSearchHome ? R.anim.recents_to_search_launcher_exit :
R.anim.recents_to_launcher_exit));
// Mark the task that is the launch target
int launchTaskIndexInStack = 0;
if (mConfig.launchedToTaskId != -1) {
if (launchState.launchedToTaskId != -1) {
ArrayList<Task> tasks = stack.getTasks();
int taskCount = tasks.size();
for (int j = 0; j < taskCount; j++) {
Task t = tasks.get(j);
if (t.key.id == mConfig.launchedToTaskId) {
if (t.key.id == launchState.launchedToTaskId) {
t.isLaunchTarget = true;
launchTaskIndexInStack = tasks.size() - j - 1;
break;
@@ -225,7 +222,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
}
// Update the top level view's visibilities
if (mConfig.launchedWithNoRecentTasks) {
if (launchState.launchedWithNoRecentTasks) {
if (mEmptyView == null) {
mEmptyView = mEmptyViewStub.inflate();
}
@@ -246,13 +243,13 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
mScrimViews.prepareEnterRecentsAnimation();
// Keep track of whether we launched from the nav bar button or via alt-tab
if (mConfig.launchedWithAltTab) {
if (launchState.launchedWithAltTab) {
MetricsLogger.count(this, "overview_trigger_alttab", 1);
} else {
MetricsLogger.count(this, "overview_trigger_nav_btn", 1);
}
// Keep track of whether we launched from an app or from home
if (mConfig.launchedFromAppWithThumbnail) {
if (launchState.launchedFromAppWithThumbnail) {
MetricsLogger.count(this, "overview_source_app", 1);
// If from an app, track the stack index of the app in the stack (for affiliated tasks)
MetricsLogger.histogram(this, "overview_source_app_index", launchTaskIndexInStack);
@@ -266,6 +263,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
/** Dismisses recents if we are already visible and the intent is to toggle the recents view */
boolean dismissRecentsToFocusedTaskOrHome(boolean checkFilteredStackState) {
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
if (ssp.isRecentsTopMost(ssp.getTopMostTask(), null)) {
// If we currently have filtered stacks, then unfilter those first
@@ -274,7 +272,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// If we have a focused Task, launch that Task now
if (mRecentsView.launchFocusedTask()) return true;
// If we launched from Home, then return to Home
if (mConfig.launchedFromHome) {
if (launchState.launchedFromHome) {
dismissRecentsToHomeRaw(true);
return true;
}
@@ -324,7 +322,8 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// initialized
RecentsTaskLoader.initialize(this);
SystemServicesProxy ssp = RecentsTaskLoader.getInstance().getSystemServicesProxy();
mConfig = RecentsConfiguration.reinitialize(this, ssp);
mConfig = RecentsConfiguration.initialize(this, ssp);
mConfig.update(this, ssp, ssp.getWindowRect());
// Initialize the widget host (the host id is static and does not change)
mAppWidgetHost = new RecentsAppWidgetHost(this, Constants.Values.App.AppWidgetHostId);
@@ -337,7 +336,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
mEmptyViewStub = (ViewStub) findViewById(R.id.empty_view_stub);
mScrimViews = new SystemBarScrimViews(this, mConfig);
mScrimViews = new SystemBarScrimViews(this);
// Bind the search app widget when we first start up
mSearchWidgetInfo = ssp.getOrBindSearchAppWidget(this, mAppWidgetHost);
@@ -358,6 +357,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
@Override
protected void onStart() {
super.onStart();
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
MetricsLogger.visible(this, MetricsLogger.OVERVIEW_ACTIVITY);
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
SystemServicesProxy ssp = loader.getSystemServicesProxy();
@@ -379,12 +379,13 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// If this is a new instance from a configuration change, then we have to manually trigger
// the enter animation state, or if recents was relaunched by AM, without going through
// the normal mechanisms
boolean wasLaunchedByAm = !mConfig.launchedFromHome && !mConfig.launchedFromAppWithThumbnail;
if (mConfig.launchedHasConfigurationChanged || wasLaunchedByAm) {
boolean wasLaunchedByAm = !launchState.launchedFromHome &&
!launchState.launchedFromAppWithThumbnail;
if (launchState.launchedHasConfigurationChanged || wasLaunchedByAm) {
onEnterAnimationTriggered();
}
if (!mConfig.launchedHasConfigurationChanged) {
if (!launchState.launchedHasConfigurationChanged) {
mRecentsView.disableLayersForOneFrame();
}
}
@@ -402,6 +403,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
protected void onStop() {
super.onStop();
MetricsLogger.hidden(this, MetricsLogger.OVERVIEW_ACTIVITY);
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
SystemServicesProxy ssp = loader.getSystemServicesProxy();
Recents.notifyVisibilityChanged(this, ssp, false);
@@ -418,12 +420,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Workaround for b/22542869, if the RecentsActivity is started again, but without going
// through SystemUI, we need to reset the config launch flags to ensure that we do not
// wait on the system to send a signal that was never queued.
mConfig.launchedFromHome = false;
mConfig.launchedFromSearchHome = false;
mConfig.launchedFromAppWithThumbnail = false;
mConfig.launchedToTaskId = -1;
mConfig.launchedWithAltTab = false;
mConfig.launchedHasConfigurationChanged = false;
launchState.launchedFromHome = false;
launchState.launchedFromSearchHome = false;
launchState.launchedFromAppWithThumbnail = false;
launchState.launchedToTaskId = -1;
launchState.launchedWithAltTab = false;
launchState.launchedHasConfigurationChanged = false;
}
@Override
@@ -475,8 +477,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_TAB: {
int altTabKeyDelay = getResources().getInteger(R.integer.recents_alt_tab_key_delay);
boolean hasRepKeyTimeElapsed = (SystemClock.elapsedRealtime() -
mLastTabKeyEventTime) > mConfig.altTabKeyDelay;
mLastTabKeyEventTime) > altTabKeyDelay;
if (event.getRepeatCount() <= 0 || hasRepKeyTimeElapsed) {
// Focus the next task in the stack
final boolean backward = event.isShiftPressed();
@@ -514,9 +517,6 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
@Override
public void onBackPressed() {
// Test mode where back does not do anything
if (mConfig.debugModeEnabled) return;
// Dismiss Recents to the focused Task or Home
dismissRecentsToFocusedTaskOrHome(true);
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.systemui.recents;
/**
* The launch state of the RecentsActivity.
*
* TODO: We will be refactoring this out RecentsConfiguration.
* Current Constraints:
* - needed in onStart() before onNewIntent()
* - needs to be reset when Recents is hidden
* - needs to be computed in Recents component
* - needs to be accessible by views
*/
public class RecentsActivityLaunchState {
public RecentsConfiguration mConfig;
public boolean launchedWithAltTab;
public boolean launchedWithNoRecentTasks;
public boolean launchedFromAppWithThumbnail;
public boolean launchedFromHome;
public boolean launchedFromSearchHome;
public boolean launchedReuseTaskStackViews;
public boolean launchedHasConfigurationChanged;
public int launchedToTaskId;
public int launchedNumVisibleTasks;
public int launchedNumVisibleThumbnails;
RecentsActivityLaunchState(RecentsConfiguration config) {
mConfig = config;
}
/** Called when the configuration has changed, and we want to reset any configuration specific
* members. */
public void updateOnConfigurationChange() {
// Reset this flag on configuration change to ensure that we recreate new task views
launchedReuseTaskStackViews = false;
// Set this flag to indicate that the configuration has changed since Recents last launched
launchedHasConfigurationChanged = true;
}
/** Returns whether the status bar scrim should be animated when shown for the first time. */
public boolean shouldAnimateStatusBarScrim() {
return launchedFromHome;
}
/** Returns whether the status bar scrim should be visible. */
public boolean hasStatusBarScrim() {
return !launchedWithNoRecentTasks;
}
/** Returns whether the nav bar scrim should be animated when shown for the first time. */
public boolean shouldAnimateNavBarScrim() {
return true;
}
/** Returns whether the nav bar scrim should be visible. */
public boolean hasNavBarScrim() {
// Only show the scrim if we have recent tasks, and if the nav bar is not transposed
return !launchedWithNoRecentTasks && mConfig.hasTransposedNavBar;
}
}

View File

@@ -16,27 +16,29 @@
package com.android.systemui.recents;
import android.app.ActivityManager;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
import android.provider.Settings;
import android.util.DisplayMetrics;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.recents.misc.Console;
import com.android.systemui.recents.misc.SystemServicesProxy;
/** A static Recents configuration for the current context
* NOTE: We should not hold any references to a Context from a static instance */
/**
* Application resources that can be retrieved from the application context and are not specifically
* tied to the current activity.
*/
public class RecentsConfiguration {
static RecentsConfiguration sInstance;
static int sPrevConfigurationHashCode;
private static final int LARGE_SCREEN_MIN_DP = 600;
private static final int XLARGE_SCREEN_MIN_DP = 720;
// Variables that are used for global calculations
private static final float STACK_SIDE_PADDING_PHONES_PCT = 0.03333f;
private static final float STACK_SIZE_PADDING_TABLETS_PCT = 0.075f;
private static final float STACK_SIZE_PADDING_LARGE_TABLETS_PCT = 0.15f;
private static final int SEARCH_BAR_SPACE_HEIGHT_PHONES_DPS = 64;
private static final int SEARCH_BAR_SPACE_HEIGHT_TABLETS_DPS = 72;
/** Levels of svelte in increasing severity/austerity. */
// No svelting.
@@ -50,123 +52,81 @@ public class RecentsConfiguration {
// Disable all thumbnail loading.
public static final int SVELTE_DISABLE_LOADING = 3;
/** Interpolators */
public Interpolator fastOutSlowInInterpolator;
public Interpolator fastOutLinearInInterpolator;
public Interpolator linearOutSlowInInterpolator;
public Interpolator quintOutInterpolator;
// Launch states
public RecentsActivityLaunchState mLaunchState = new RecentsActivityLaunchState(this);
/** Filtering */
public int filteringCurrentViewsAnimDuration;
public int filteringNewViewsAnimDuration;
/** Insets */
public Rect systemInsets = new Rect();
public Rect displayRect = new Rect();
/** Layout */
boolean isLandscape;
// TODO: Values determined by the current context, needs to be refactored into something that is
// agnostic of the activity context, but still calculable from the Recents component for
// the transition into recents
boolean hasTransposedSearchBar;
boolean hasTransposedNavBar;
/** Loading */
public int maxNumTasksToLoad;
/** Search bar */
public int searchBarSpaceHeightPx;
/** Task stack */
public int taskStackScrollDuration;
public int taskStackMaxDim;
public int taskStackTopPaddingPx;
public int dismissAllButtonSizePx;
public float taskStackWidthPaddingPct;
public float taskStackOverscrollPct;
/** Transitions */
public int transitionEnterFromAppDelay;
public int transitionEnterFromHomeDelay;
/** Task view animation and styles */
public int taskViewEnterFromAppDuration;
public int taskViewEnterFromHomeDuration;
public int taskViewEnterFromHomeStaggerDelay;
public int taskViewExitToAppDuration;
public int taskViewExitToHomeDuration;
public int taskViewRemoveAnimDuration;
public int taskViewRemoveAnimTranslationXPx;
public int taskViewTranslationZMinPx;
public int taskViewTranslationZMaxPx;
public int taskViewRoundedCornerRadiusPx;
public int taskViewHighlightPx;
public int taskViewAffiliateGroupEnterOffsetPx;
public float taskViewThumbnailAlpha;
/** Task bar colors */
public int taskBarViewDefaultBackgroundColor;
public int taskBarViewLightTextColor;
public int taskBarViewDarkTextColor;
public int taskBarViewHighlightColor;
public float taskBarViewAffiliationColorMinAlpha;
/** Task bar size & animations */
public int taskBarHeight;
public int taskBarDismissDozeDelaySeconds;
/** Nav bar scrim */
public int navBarScrimEnterDuration;
/** Launch states */
public boolean launchedWithAltTab;
public boolean launchedWithNoRecentTasks;
public boolean launchedFromAppWithThumbnail;
public boolean launchedFromHome;
public boolean launchedFromSearchHome;
public boolean launchedReuseTaskStackViews;
public boolean launchedHasConfigurationChanged;
public int launchedToTaskId;
public int launchedNumVisibleTasks;
public int launchedNumVisibleThumbnails;
// Since the positions in Recents has to be calculated globally (before the RecentsActivity
// starts), we need to calculate some resource values ourselves, instead of relying on framework
// resources.
public final boolean isLargeScreen;
public final boolean isXLargeScreen;
public final int smallestWidth;
/** Misc **/
public boolean useHardwareLayers;
public int altTabKeyDelay;
public boolean fakeShadows;
public int svelteLevel;
public int searchBarSpaceHeightPx;
/** Dev options and global settings */
public boolean multiWindowEnabled;
public boolean lockToAppEnabled;
public boolean developerOptionsEnabled;
public boolean debugModeEnabled;
public int svelteLevel;
/** Private constructor */
private RecentsConfiguration(Context context) {
// Properties that don't have to be reloaded with each configuration change can be loaded
// here.
private RecentsConfiguration(Context context, SystemServicesProxy ssp) {
// Load only resources that can not change after the first load either through developer
// settings or via multi window
Context appContext = context.getApplicationContext();
Resources res = appContext.getResources();
useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers);
fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
svelteLevel = res.getInteger(R.integer.recents_svelte_level);
// Interpolators
fastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
fastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_linear_in);
linearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.linear_out_slow_in);
quintOutInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.decelerate_quint);
float density = context.getResources().getDisplayMetrics().density;
smallestWidth = ssp.getDeviceSmallestWidth();
isLargeScreen = smallestWidth >= (int) (density * LARGE_SCREEN_MIN_DP);
isXLargeScreen = smallestWidth >= (int) (density * XLARGE_SCREEN_MIN_DP);
searchBarSpaceHeightPx = isLargeScreen ?
(int) (density * SEARCH_BAR_SPACE_HEIGHT_TABLETS_DPS) :
(int) (density * SEARCH_BAR_SPACE_HEIGHT_PHONES_DPS);
if (isLargeScreen) {
taskStackWidthPaddingPct = STACK_SIZE_PADDING_TABLETS_PCT;
} else if (isXLargeScreen) {
taskStackWidthPaddingPct = STACK_SIZE_PADDING_LARGE_TABLETS_PCT;
} else {
taskStackWidthPaddingPct = STACK_SIDE_PADDING_PHONES_PCT;
}
}
/**
* Updates the configuration based on the current state of the system
*/
void update(Context context, SystemServicesProxy ssp, Rect windowRect) {
// Only update resources that can change after the first load, either through developer
// settings or via multi window
lockToAppEnabled = ssp.getSystemSetting(context,
Settings.System.LOCK_TO_APP_ENABLED) != 0;
multiWindowEnabled = "true".equals(ssp.getSystemProperty("persist.sys.debug.multi_window"));
// Recompute some values based on the given state, since we can not rely on the resource
// system to get certain values.
boolean isLandscape = windowRect.width() > windowRect.height();
hasTransposedNavBar = isLandscape && isLargeScreen && !isXLargeScreen;
hasTransposedSearchBar = isLandscape && isLargeScreen && !isXLargeScreen;
}
/** Updates the configuration to the current context */
public static RecentsConfiguration reinitialize(Context context, SystemServicesProxy ssp) {
public static RecentsConfiguration initialize(Context context, SystemServicesProxy ssp) {
if (sInstance == null) {
sInstance = new RecentsConfiguration(context);
sInstance = new RecentsConfiguration(context, ssp);
}
int configHashCode = context.getResources().getConfiguration().hashCode();
if (sPrevConfigurationHashCode != configHashCode) {
sInstance.update(context);
sPrevConfigurationHashCode = configHashCode;
}
sInstance.reinitializeWithApplicationContext(context.getApplicationContext(), ssp);
return sInstance;
}
@@ -175,145 +135,18 @@ public class RecentsConfiguration {
return sInstance;
}
/** Updates the state, given the specified context */
void update(Context context) {
Resources res = context.getResources();
DisplayMetrics dm = res.getDisplayMetrics();
// Debug mode
debugModeEnabled = Prefs.getBoolean(context, Prefs.Key.DEBUG_MODE_ENABLED,
false /* defaultValue */);
if (debugModeEnabled) {
Console.Enabled = true;
}
// Layout
isLandscape = res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
hasTransposedSearchBar = res.getBoolean(R.bool.recents_has_transposed_search_bar);
hasTransposedNavBar = res.getBoolean(R.bool.recents_has_transposed_nav_bar);
// Insets
displayRect.set(0, 0, dm.widthPixels, dm.heightPixels);
// Filtering
filteringCurrentViewsAnimDuration =
res.getInteger(R.integer.recents_filter_animate_current_views_duration);
filteringNewViewsAnimDuration =
res.getInteger(R.integer.recents_filter_animate_new_views_duration);
// Loading
maxNumTasksToLoad = ActivityManager.getMaxRecentTasksStatic();
// Search Bar
searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
// Task stack
taskStackScrollDuration =
res.getInteger(R.integer.recents_animate_task_stack_scroll_duration);
taskStackWidthPaddingPct = res.getFloat(R.dimen.recents_stack_width_padding_percentage);
taskStackOverscrollPct = res.getFloat(R.dimen.recents_stack_overscroll_percentage);
taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
dismissAllButtonSizePx = res.getDimensionPixelSize(R.dimen.recents_dismiss_all_button_size);
// Transition
transitionEnterFromAppDelay =
res.getInteger(R.integer.recents_enter_from_app_transition_duration);
transitionEnterFromHomeDelay =
res.getInteger(R.integer.recents_enter_from_home_transition_duration);
// Task view animation and styles
taskViewEnterFromAppDuration =
res.getInteger(R.integer.recents_task_enter_from_app_duration);
taskViewEnterFromHomeDuration =
res.getInteger(R.integer.recents_task_enter_from_home_duration);
taskViewEnterFromHomeStaggerDelay =
res.getInteger(R.integer.recents_task_enter_from_home_stagger_delay);
taskViewExitToAppDuration =
res.getInteger(R.integer.recents_task_exit_to_app_duration);
taskViewExitToHomeDuration =
res.getInteger(R.integer.recents_task_exit_to_home_duration);
taskViewRemoveAnimDuration =
res.getInteger(R.integer.recents_animate_task_view_remove_duration);
taskViewRemoveAnimTranslationXPx =
res.getDimensionPixelSize(R.dimen.recents_task_view_remove_anim_translation_x);
taskViewRoundedCornerRadiusPx =
res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
taskViewHighlightPx = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
taskViewTranslationZMinPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
taskViewTranslationZMaxPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max);
taskViewAffiliateGroupEnterOffsetPx =
res.getDimensionPixelSize(R.dimen.recents_task_view_affiliate_group_enter_offset);
taskViewThumbnailAlpha = res.getFloat(R.dimen.recents_task_view_thumbnail_alpha);
// Task bar colors
taskBarViewDefaultBackgroundColor = context.getColor(
R.color.recents_task_bar_default_background_color);
taskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color);
taskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color);
taskBarViewHighlightColor = context.getColor(R.color.recents_task_bar_highlight_color);
taskBarViewAffiliationColorMinAlpha = res.getFloat(
R.dimen.recents_task_affiliation_color_min_alpha_percentage);
// Task bar size & animations
taskBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
taskBarDismissDozeDelaySeconds =
res.getInteger(R.integer.recents_task_bar_dismiss_delay_seconds);
// Nav bar scrim
navBarScrimEnterDuration =
res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration);
// Misc
useHardwareLayers = res.getBoolean(R.bool.config_recents_use_hardware_layers);
altTabKeyDelay = res.getInteger(R.integer.recents_alt_tab_key_delay);
fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
svelteLevel = res.getInteger(R.integer.recents_svelte_level);
}
/** Updates the system insets */
public void updateSystemInsets(Rect insets) {
systemInsets.set(insets);
}
/** Updates the states that need to be re-read from the application context. */
void reinitializeWithApplicationContext(Context context, SystemServicesProxy ssp) {
// Check if the developer options are enabled
developerOptionsEnabled = ssp.getGlobalSetting(context,
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED) != 0;
lockToAppEnabled = ssp.getSystemSetting(context,
Settings.System.LOCK_TO_APP_ENABLED) != 0;
multiWindowEnabled = "true".equals(ssp.getSystemProperty("persist.sys.debug.multi_window"));
/**
* Returns the activity launch state.
* TODO: This will be refactored out of RecentsConfiguration.
*/
public RecentsActivityLaunchState getLaunchState() {
return mLaunchState;
}
/** Called when the configuration has changed, and we want to reset any configuration specific
* members. */
public void updateOnConfigurationChange() {
// Reset this flag on configuration change to ensure that we recreate new task views
launchedReuseTaskStackViews = false;
// Set this flag to indicate that the configuration has changed since Recents last launched
launchedHasConfigurationChanged = true;
}
/** Returns whether the status bar scrim should be animated when shown for the first time. */
public boolean shouldAnimateStatusBarScrim() {
return launchedFromHome;
}
/** Returns whether the status bar scrim should be visible. */
public boolean hasStatusBarScrim() {
return !launchedWithNoRecentTasks;
}
/** Returns whether the nav bar scrim should be animated when shown for the first time. */
public boolean shouldAnimateNavBarScrim() {
return true;
}
/** Returns whether the nav bar scrim should be visible. */
public boolean hasNavBarScrim() {
// Only show the scrim if we have recent tasks, and if the nav bar is not transposed
return !launchedWithNoRecentTasks && (!hasTransposedNavBar || !isLandscape);
mLaunchState.updateOnConfigurationChange();
}
/**
@@ -322,14 +155,17 @@ public class RecentsConfiguration {
*/
public void getAvailableTaskStackBounds(Rect windowBounds, int topInset,
int rightInset, Rect searchBarBounds, Rect taskStackBounds) {
if (isLandscape && hasTransposedSearchBar) {
// In landscape, the search bar appears on the left, but we overlay it on top
taskStackBounds.set(windowBounds.left, windowBounds.top + topInset,
windowBounds.right - rightInset, windowBounds.bottom);
if (hasTransposedNavBar) {
// In landscape phones, the search bar appears on the left, but we overlay it on top
int swInset = getInsetToSmallestWidth(windowBounds.right - rightInset -
windowBounds.left);
taskStackBounds.set(windowBounds.left + swInset, windowBounds.top + topInset,
windowBounds.right - swInset - rightInset, windowBounds.bottom);
} else {
// In portrait, the search bar appears on the top (which already has the inset)
taskStackBounds.set(windowBounds.left, searchBarBounds.bottom,
windowBounds.right, windowBounds.bottom);
int swInset = getInsetToSmallestWidth(windowBounds.right - windowBounds.left);
taskStackBounds.set(windowBounds.left + swInset, searchBarBounds.bottom,
windowBounds.right - swInset, windowBounds.bottom);
}
}
@@ -340,8 +176,8 @@ public class RecentsConfiguration {
public void getSearchBarBounds(Rect windowBounds, int topInset, Rect searchBarSpaceBounds) {
// Return empty rects if search is not enabled
int searchBarSize = searchBarSpaceHeightPx;
if (isLandscape && hasTransposedSearchBar) {
// In landscape, the search bar appears on the left
if (hasTransposedSearchBar) {
// In landscape phones, the search bar appears on the left
searchBarSpaceBounds.set(windowBounds.left, windowBounds.top + topInset,
windowBounds.left + searchBarSize, windowBounds.bottom);
} else {
@@ -350,4 +186,14 @@ public class RecentsConfiguration {
windowBounds.right, windowBounds.top + topInset + searchBarSize);
}
}
/**
* Constrain the width of the landscape stack to the smallest width of the device.
*/
private int getInsetToSmallestWidth(int availableWidth) {
if (availableWidth > smallestWidth) {
return (availableWidth - smallestWidth) / 2;
}
return 0;
}
}

View File

@@ -21,7 +21,6 @@ import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Rect;
import android.os.Bundle;

View File

@@ -39,7 +39,6 @@ import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.systemui.R;
import java.util.ArrayList;

View File

@@ -32,7 +32,6 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.PackageParser;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -56,18 +55,18 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import android.util.MutableBoolean;
import android.util.MutableFloat;
import android.util.MutableInt;
import android.util.Pair;
import android.util.SparseArray;
import android.util.Size;
import android.view.Display;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import com.android.internal.app.AssistUtils;
import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsConfiguration;
import java.io.IOException;
import java.util.ArrayList;
@@ -661,6 +660,18 @@ public class SystemServicesProxy {
return SystemProperties.get(key);
}
/**
* Returns the smallest width/height.
*/
public int getDeviceSmallestWidth() {
if (mWm == null) return 0;
Point smallestSizeRange = new Point();
Point largestSizeRange = new Point();
mWm.getDefaultDisplay().getCurrentSizeRange(smallestSizeRange, largestSizeRange);
return smallestSizeRange.x;
}
/**
* Returns the display rect.
*/
@@ -675,7 +686,7 @@ public class SystemServicesProxy {
}
/**
* Returns the window rect.
* Returns the window rect for the RecentsActivity, based on the dimensions of the home stack.
*/
public Rect getWindowRect() {
Rect windowRect = new Rect();

View File

@@ -23,7 +23,6 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.UserHandle;
import android.util.Log;
import android.util.SparseArray;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -76,7 +75,7 @@ public class RecentsTaskLoadPlan {
* An optimization to preload the raw list of tasks.
*/
public synchronized void preloadRawTasks(boolean isTopTaskHome) {
mRawTasks = mSystemServicesProxy.getRecentTasks(mConfig.maxNumTasksToLoad,
mRawTasks = mSystemServicesProxy.getRecentTasks(ActivityManager.getMaxRecentTasksStatic(),
UserHandle.CURRENT.getIdentifier(), isTopTaskHome);
Collections.reverse(mRawTasks);
@@ -125,7 +124,7 @@ public class RecentsTaskLoadPlan {
activityLabel, mSystemServicesProxy, res);
Drawable activityIcon = loader.getAndUpdateActivityIcon(taskKey, t.taskDescription,
mSystemServicesProxy, res, infoHandle, false);
int activityColor = loader.getActivityPrimaryColor(t.taskDescription, mConfig);
int activityColor = loader.getActivityPrimaryColor(t.taskDescription, res);
// Update the activity info cache
if (!hadCachedActivityInfo && infoHandle.info != null) {
@@ -153,7 +152,7 @@ public class RecentsTaskLoadPlan {
// Initialize the stacks
mStack = new TaskStack();
mStack.setTasks(stackTasks);
mStack.createAffiliatedGroupings(mConfig);
mStack.createAffiliatedGroupings(mContext);
}
/**

View File

@@ -27,7 +27,6 @@ import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
@@ -248,7 +247,7 @@ class TaskResourceLoader implements Runnable {
}
/* Recents task loader
* NOTE: We should not hold any references to a Context from a static instance */
* NOTE: We should not hold any references to non-application Context from a static instance */
public class RecentsTaskLoader {
private static final String TAG = "RecentsTaskLoader";
@@ -438,12 +437,11 @@ public class RecentsTaskLoader {
}
/** Returns the activity's primary color. */
public int getActivityPrimaryColor(ActivityManager.TaskDescription td,
RecentsConfiguration config) {
public int getActivityPrimaryColor(ActivityManager.TaskDescription td, Resources res) {
if (td != null && td.getPrimaryColor() != 0) {
return td.getPrimaryColor();
}
return config.taskBarViewDefaultBackgroundColor;
return res.getColor(R.color.recents_task_bar_default_background_color);
}
/** Returns the size of the app icon cache. */

View File

@@ -16,11 +16,12 @@
package com.android.systemui.recents.model;
import android.content.Context;
import android.graphics.Color;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.NamedCounter;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.R;
import java.util.ArrayList;
import java.util.Collections;
@@ -367,7 +368,7 @@ public class TaskStack {
/**
* Temporary: This method will simulate affiliation groups by
*/
public void createAffiliatedGroupings(RecentsConfiguration config) {
public void createAffiliatedGroupings(Context context) {
if (Constants.DebugFlags.App.EnableSimulatedTaskGroups) {
HashMap<Task.TaskKey, Task> taskMap = new HashMap<Task.TaskKey, Task>();
// Sort all tasks by increasing firstActiveTime of the task
@@ -452,7 +453,8 @@ public class TaskStack {
tasksMap.put(t.key, t);
}
// Update the task colors for each of the groups
float minAlpha = config.taskBarViewAffiliationColorMinAlpha;
float minAlpha = context.getResources().getFloat(
R.dimen.recents_task_affiliation_color_min_alpha_percentage);
int taskGroupCount = mGroups.size();
for (int i = 0; i < taskGroupCount; i++) {
TaskGrouping group = mGroups.get(i);

View File

@@ -89,7 +89,8 @@ class FakeShadowDrawable extends Drawable {
mCornerShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mCornerShadowPaint.setStyle(Paint.Style.FILL);
mCornerShadowPaint.setDither(true);
mCornerRadius = config.taskViewRoundedCornerRadiusPx;
mCornerRadius = resources.getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
mCardBounds = new RectF();
mEdgeShadowPaint = new Paint(mCornerShadowPaint);
}

View File

@@ -38,8 +38,9 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManagerGlobal;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
@@ -83,6 +84,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
TaskStackView mTaskStackView;
RecentsAppWidgetHostView mSearchBar;
RecentsViewCallbacks mCb;
Interpolator mFastOutSlowInInterpolator;
Rect mSystemInsets = new Rect();
public RecentsView(Context context) {
super(context);
@@ -100,6 +104,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
super(context, attrs, defStyleAttr, defStyleRes);
mConfig = RecentsConfiguration.getInstance();
mInflater = LayoutInflater.from(context);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
}
/** Sets the callbacks */
@@ -109,7 +115,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** Set/get the bsp root node */
public void setTaskStack(TaskStack stack) {
if (mConfig.launchedReuseTaskStackViews) {
if (mConfig.getLaunchState().launchedReuseTaskStackViews) {
if (mTaskStackView != null) {
// If onRecentsHidden is not triggered, we need to the stack view again here
mTaskStackView.reset();
@@ -278,7 +284,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
// Get the search bar bounds and measure the search bar layout
Rect searchBarSpaceBounds = new Rect();
if (mSearchBar != null) {
mConfig.getSearchBarBounds(new Rect(0, 0, width, height), mConfig.systemInsets.top,
mConfig.getSearchBarBounds(new Rect(0, 0, width, height), mSystemInsets.top,
searchBarSpaceBounds);
mSearchBar.measure(
MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY),
@@ -286,8 +292,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
}
Rect taskStackBounds = new Rect();
mConfig.getAvailableTaskStackBounds(new Rect(0, 0, width, height), mConfig.systemInsets.top,
mConfig.systemInsets.right, searchBarSpaceBounds, taskStackBounds);
mConfig.getAvailableTaskStackBounds(new Rect(0, 0, width, height), mSystemInsets.top,
mSystemInsets.right, searchBarSpaceBounds, taskStackBounds);
if (mTaskStackView != null && mTaskStackView.getVisibility() != GONE) {
mTaskStackView.setTaskStackBounds(taskStackBounds);
mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
@@ -306,7 +312,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
Rect searchBarSpaceBounds = new Rect();
if (mSearchBar != null) {
mConfig.getSearchBarBounds(measuredRect,
mConfig.systemInsets.top, searchBarSpaceBounds);
mSystemInsets.top, searchBarSpaceBounds);
mSearchBar.layout(searchBarSpaceBounds.left, searchBarSpaceBounds.top,
searchBarSpaceBounds.right, searchBarSpaceBounds.bottom);
}
@@ -318,8 +324,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
// Update the configuration with the latest system insets and trigger a relayout
mConfig.updateSystemInsets(insets.getSystemWindowInsets());
mSystemInsets.set(insets.getSystemWindowInsets());
requestLayout();
return insets.consumeSystemWindowInsets();
}
@@ -548,7 +553,7 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
// outside the display rect (to ensure we don't animate from too far away)
sourceView = stackView;
offsetX = transform.rect.left;
offsetY = mConfig.displayRect.height();
offsetY = getMeasuredHeight();
} else {
sourceView = tv.mThumbnailView;
}
@@ -700,11 +705,13 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
public void onTaskStackFilterTriggered() {
// Hide the search bar
if (mSearchBar != null) {
int filterDuration = getResources().getInteger(
R.integer.recents_filter_animate_current_views_duration);
mSearchBar.animate()
.alpha(0f)
.setStartDelay(0)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(mConfig.filteringCurrentViewsAnimDuration)
.setInterpolator(mFastOutSlowInInterpolator)
.setDuration(filterDuration)
.withLayer()
.start();
}
@@ -714,11 +721,13 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
public void onTaskStackUnfilterTriggered() {
// Show the search bar
if (mSearchBar != null) {
int filterDuration = getResources().getInteger(
R.integer.recents_filter_animate_new_views_duration);
mSearchBar.animate()
.alpha(1f)
.setStartDelay(0)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(mConfig.filteringNewViewsAnimDuration)
.setInterpolator(mFastOutSlowInInterpolator)
.setDuration(filterDuration)
.withLayer()
.start();
}

View File

@@ -22,13 +22,15 @@ import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import com.android.systemui.recents.RecentsConfiguration;
/**
* This class facilitates swipe to dismiss. It defines an interface to be implemented by the
@@ -46,6 +48,7 @@ public class SwipeHelper {
public static final int Y = 1;
private static LinearInterpolator sLinearInterpolator = new LinearInterpolator();
private Interpolator mLinearOutSlowInInterpolator;
private float SWIPE_ESCAPE_VELOCITY = 100f; // dp/sec
private int DEFAULT_ESCAPE_ANIMATION_DURATION = 75; // ms
@@ -74,13 +77,15 @@ public class SwipeHelper {
public boolean mAllowSwipeTowardsEnd = true;
private boolean mRtl;
public SwipeHelper(int swipeDirection, Callback callback, float densityScale,
public SwipeHelper(Context context, int swipeDirection, Callback callback, float densityScale,
float pagingTouchSlop) {
mCallback = callback;
mSwipeDirection = swipeDirection;
mVelocityTracker = VelocityTracker.obtain();
mDensityScale = densityScale;
mPagingTouchSlop = pagingTouchSlop;
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.linear_out_slow_in);
}
public void setDensityScale(float densityScale) {
@@ -265,7 +270,7 @@ public class SwipeHelper {
ValueAnimator anim = createTranslationAnimation(view, 0);
int duration = SNAP_ANIM_LEN;
anim.setDuration(duration);
anim.setInterpolator(RecentsConfiguration.getInstance().linearOutSlowInInterpolator);
anim.setInterpolator(mLinearOutSlowInInterpolator);
anim.addUpdateListener(new AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {

View File

@@ -17,13 +17,19 @@
package com.android.systemui.recents.views;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.systemui.R;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
/** Manages the scrims for the various system bars. */
public class SystemBarScrimViews {
Context mContext;
RecentsConfiguration mConfig;
View mStatusBarScrimView;
@@ -34,10 +40,22 @@ public class SystemBarScrimViews {
boolean mHasStatusBarScrim;
boolean mShouldAnimateNavBarScrim;
public SystemBarScrimViews(Activity activity, RecentsConfiguration config) {
mConfig = config;
int mNavBarScrimEnterDuration;
Interpolator mFastOutSlowInInterpolator;
Interpolator mQuintOutInterpolator;
public SystemBarScrimViews(Activity activity) {
mContext = activity;
mConfig = RecentsConfiguration.getInstance();
mStatusBarScrimView = activity.findViewById(R.id.status_bar_scrim);
mNavBarScrimView = activity.findViewById(R.id.nav_bar_scrim);
mNavBarScrimEnterDuration = activity.getResources().getInteger(
R.integer.recents_nav_bar_scrim_enter_duration);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(activity,
com.android.internal.R.interpolator.fast_out_slow_in);
mQuintOutInterpolator = AnimationUtils.loadInterpolator(activity,
com.android.internal.R.interpolator.decelerate_quint);
}
/**
@@ -45,10 +63,11 @@ public class SystemBarScrimViews {
* the first draw.
*/
public void prepareEnterRecentsAnimation() {
mHasNavBarScrim = mConfig.hasNavBarScrim();
mShouldAnimateNavBarScrim = mConfig.shouldAnimateNavBarScrim();
mHasStatusBarScrim = mConfig.hasStatusBarScrim();
mShouldAnimateStatusBarScrim = mConfig.shouldAnimateStatusBarScrim();
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
mHasNavBarScrim = launchState.hasNavBarScrim();
mShouldAnimateNavBarScrim = launchState.shouldAnimateNavBarScrim();
mHasStatusBarScrim = launchState.hasStatusBarScrim();
mShouldAnimateStatusBarScrim = launchState.shouldAnimateStatusBarScrim();
mNavBarScrimView.setVisibility(mHasNavBarScrim && !mShouldAnimateNavBarScrim ?
View.VISIBLE : View.INVISIBLE);
@@ -60,15 +79,21 @@ public class SystemBarScrimViews {
* Starts animating the scrim views when entering Recents.
*/
public void startEnterRecentsAnimation() {
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
int transitionEnterFromAppDelay = mContext.getResources().getInteger(
R.integer.recents_enter_from_app_transition_duration);
int transitionEnterFromHomeDelay = mContext.getResources().getInteger(
R.integer.recents_enter_from_home_transition_duration);
if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
mStatusBarScrimView.setTranslationY(-mStatusBarScrimView.getMeasuredHeight());
mStatusBarScrimView.animate()
.translationY(0)
.setStartDelay(mConfig.launchedFromHome ?
mConfig.transitionEnterFromHomeDelay :
mConfig.transitionEnterFromAppDelay)
.setDuration(mConfig.navBarScrimEnterDuration)
.setInterpolator(mConfig.quintOutInterpolator)
.setStartDelay(launchState.launchedFromHome ?
transitionEnterFromHomeDelay :
transitionEnterFromAppDelay)
.setDuration(mNavBarScrimEnterDuration)
.setInterpolator(mQuintOutInterpolator)
.withStartAction(new Runnable() {
@Override
public void run() {
@@ -81,11 +106,11 @@ public class SystemBarScrimViews {
mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
mNavBarScrimView.animate()
.translationY(0)
.setStartDelay(mConfig.launchedFromHome ?
mConfig.transitionEnterFromHomeDelay :
mConfig.transitionEnterFromAppDelay)
.setDuration(mConfig.navBarScrimEnterDuration)
.setInterpolator(mConfig.quintOutInterpolator)
.setStartDelay(launchState.launchedFromHome ?
transitionEnterFromHomeDelay :
transitionEnterFromAppDelay)
.setDuration(mNavBarScrimEnterDuration)
.setInterpolator(mQuintOutInterpolator)
.withStartAction(new Runnable() {
@Override
public void run() {
@@ -101,20 +126,22 @@ public class SystemBarScrimViews {
* going home).
*/
public void startExitRecentsAnimation() {
int taskViewExitToAppDuration = mContext.getResources().getInteger(
R.integer.recents_task_exit_to_app_duration);
if (mHasStatusBarScrim && mShouldAnimateStatusBarScrim) {
mStatusBarScrimView.animate()
.translationY(-mStatusBarScrimView.getMeasuredHeight())
.setStartDelay(0)
.setDuration(mConfig.taskViewExitToAppDuration)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(taskViewExitToAppDuration)
.setInterpolator(mFastOutSlowInInterpolator)
.start();
}
if (mHasNavBarScrim && mShouldAnimateNavBarScrim) {
mNavBarScrimView.animate()
.translationY(mNavBarScrimView.getMeasuredHeight())
.setStartDelay(0)
.setDuration(mConfig.taskViewExitToAppDuration)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(taskViewExitToAppDuration)
.setInterpolator(mFastOutSlowInInterpolator)
.start();
}
}

View File

@@ -29,10 +29,10 @@ import android.view.View;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
@@ -117,14 +117,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Set the stack first
setStack(stack);
mConfig = RecentsConfiguration.getInstance();
mViewPool = new ViewPool<TaskView, Task>(context, this);
mViewPool = new ViewPool<>(context, this);
mInflater = LayoutInflater.from(context);
mLayoutAlgorithm = new TaskStackViewLayoutAlgorithm(mConfig);
mFilterAlgorithm = new TaskStackViewFilterAlgorithm(mConfig, this, mViewPool);
mStackScroller = new TaskStackViewScroller(context, mConfig, mLayoutAlgorithm);
mLayoutAlgorithm = new TaskStackViewLayoutAlgorithm(context, mConfig);
mFilterAlgorithm = new TaskStackViewFilterAlgorithm(this, mViewPool);
mStackScroller = new TaskStackViewScroller(context, mLayoutAlgorithm);
mStackScroller.setCallbacks(this);
mTouchHandler = new TaskStackViewTouchHandler(context, this, mConfig, mStackScroller);
mUIDozeTrigger = new DozeTrigger(mConfig.taskBarDismissDozeDelaySeconds, new Runnable() {
mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
int taskBarDismissDozeDelaySeconds = getResources().getInteger(
R.integer.recents_task_bar_dismiss_delay_seconds);
mUIDozeTrigger = new DozeTrigger(taskBarDismissDozeDelaySeconds, new Runnable() {
@Override
public void run() {
// Show the task bar dismiss buttons
@@ -731,8 +734,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int height = MeasureSpec.getSize(heightMeasureSpec);
// Compute our stack/task rects
computeRects(width, height, mTaskStackBounds, mConfig.launchedWithAltTab,
mConfig.launchedFromHome);
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
computeRects(width, height, mTaskStackBounds, launchState.launchedWithAltTab,
launchState.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
@@ -764,9 +768,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Measure the dismiss button
if (mDismissAllButton != null) {
int taskRectWidth = mLayoutAlgorithm.mTaskRect.width();
int dismissAllButtonHeight = getResources().getDimensionPixelSize(
R.dimen.recents_dismiss_all_button_size);
mDismissAllButton.measure(
MeasureSpec.makeMeasureSpec(taskRectWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mConfig.dismissAllButtonSizePx, MeasureSpec.EXACTLY));
MeasureSpec.makeMeasureSpec(dismissAllButtonHeight, MeasureSpec.EXACTLY));
}
setMeasuredDimension(width, height);
@@ -847,13 +853,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// When Alt-Tabbing, focus the previous task (but leave the animation until we finish the
// enter animation).
if (mConfig.launchedWithAltTab) {
if (mConfig.launchedFromAppWithThumbnail) {
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
if (launchState.launchedWithAltTab) {
if (launchState.launchedFromAppWithThumbnail) {
focusTask(Math.max(0, mStack.getTaskCount() - 2), false,
mConfig.launchedHasConfigurationChanged);
launchState.launchedHasConfigurationChanged);
} else {
focusTask(Math.max(0, mStack.getTaskCount() - 1), false,
mConfig.launchedHasConfigurationChanged);
launchState.launchedHasConfigurationChanged);
}
}
@@ -924,7 +931,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Start the focus animation when alt-tabbing
ArrayList<Task> tasks = mStack.getTasks();
if (mConfig.launchedWithAltTab && !mConfig.launchedHasConfigurationChanged &&
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
if (launchState.launchedWithAltTab &&
!launchState.launchedHasConfigurationChanged &&
0 <= mFocusedTaskIndex && mFocusedTaskIndex < tasks.size()) {
TaskView tv = getChildViewForTask(tasks.get(mFocusedTaskIndex));
if (tv != null) {
@@ -1115,7 +1124,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
// Update the min/max scroll and animate other task views into their new positions
updateMinMaxScroll(true, mConfig.launchedWithAltTab, mConfig.launchedFromHome);
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
updateMinMaxScroll(true, launchState.launchedWithAltTab, launchState.launchedFromHome);
// Offset the stack by as much as the anchor task would otherwise move back
if (pullStackForward) {
@@ -1133,7 +1143,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
TaskView frontTv = getChildViewForTask(newFrontMostTask);
if (frontTv != null) {
frontTv.onTaskBound(newFrontMostTask);
frontTv.fadeInActionButton(0, mConfig.taskViewEnterFromAppDuration);
frontTv.fadeInActionButton(0, getResources().getInteger(
R.integer.recents_task_enter_from_app_duration));
}
}
@@ -1384,7 +1395,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
if (nextTv != null) {
// Focus the next task, and only animate the visible state if we are launched
// from Alt-Tab
nextTv.setFocusedTask(mConfig.launchedWithAltTab);
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
nextTv.setFocusedTask(launchState.launchedWithAltTab);
}
}
}

View File

@@ -17,8 +17,8 @@
package com.android.systemui.recents.views;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.model.Task;
import com.android.systemui.R;
import java.util.ArrayList;
import java.util.HashMap;
@@ -27,13 +27,10 @@ import java.util.List;
/* The layout logic for a TaskStackView */
public class TaskStackViewFilterAlgorithm {
RecentsConfiguration mConfig;
TaskStackView mStackView;
ViewPool<TaskView, Task> mViewPool;
public TaskStackViewFilterAlgorithm(RecentsConfiguration config, TaskStackView stackView,
ViewPool<TaskView, Task> viewPool) {
mConfig = config;
public TaskStackViewFilterAlgorithm(TaskStackView stackView, ViewPool<TaskView, Task> viewPool) {
mStackView = stackView;
mViewPool = viewPool;
}
@@ -126,7 +123,8 @@ public class TaskStackViewFilterAlgorithm {
}
}
}
return mConfig.filteringNewViewsAnimDuration;
return mStackView.getResources().getInteger(
R.integer.recents_filter_animate_new_views_duration);
}
/**
@@ -172,7 +170,8 @@ public class TaskStackViewFilterAlgorithm {
childViewTransformsOut.put(tv, toTransform);
offset++;
}
return mConfig.filteringCurrentViewsAnimDuration;
return mStackView.getResources().getInteger(
R.integer.recents_filter_animate_current_views_duration);
}
}

View File

@@ -16,11 +16,13 @@
package com.android.systemui.recents.views;
import android.content.Context;
import android.graphics.Rect;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.R;
import java.util.ArrayList;
import java.util.HashMap;
@@ -48,6 +50,7 @@ public class TaskStackViewLayoutAlgorithm {
}
}
Context mContext;
RecentsConfiguration mConfig;
// The various rects that define the stack view
@@ -71,7 +74,8 @@ public class TaskStackViewLayoutAlgorithm {
static float[] xp;
static float[] px;
public TaskStackViewLayoutAlgorithm(RecentsConfiguration config) {
public TaskStackViewLayoutAlgorithm(Context context, RecentsConfiguration config) {
mContext = context;
mConfig = config;
// Precompute the path
@@ -87,7 +91,8 @@ public class TaskStackViewLayoutAlgorithm {
mStackVisibleRect.bottom = mViewRect.bottom;
int widthPadding = (int) (mConfig.taskStackWidthPaddingPct * mStackRect.width());
int heightPadding = mConfig.taskStackTopPaddingPx;
int heightPadding = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_stack_top_padding);
mStackRect.inset(widthPadding, heightPadding);
// Compute the task rect
@@ -98,7 +103,8 @@ public class TaskStackViewLayoutAlgorithm {
// Update the affiliation offsets
float visibleTaskPct = 0.5f;
mWithinAffiliationOffset = mConfig.taskBarHeight;
mWithinAffiliationOffset = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_bar_height);
mBetweenAffiliationOffset = (int) (visibleTaskPct * mTaskRect.height());
}
@@ -134,8 +140,10 @@ public class TaskStackViewLayoutAlgorithm {
mStackRect.bottom));
float pDismissAllButtonOffset = 0f;
if (Constants.DebugFlags.App.EnableDismissAll) {
int dismissAllButtonHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_dismiss_all_button_size);
pDismissAllButtonOffset = pAtBottomOfStackRect -
screenYToCurveProgress(mStackVisibleRect.bottom - mConfig.dismissAllButtonSizePx);
screenYToCurveProgress(mStackVisibleRect.bottom - dismissAllButtonHeight);
}
// Update the task offsets
@@ -177,6 +185,8 @@ public class TaskStackViewLayoutAlgorithm {
// Walk backwards in the task stack and count the number of tasks and visible thumbnails
int taskHeight = mTaskRect.height();
int taskBarHeight = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_bar_height);
int numVisibleTasks = 1;
int numVisibleThumbnails = 1;
float progress = mTaskProgressMap.get(tasks.get(tasks.size() - 1).key) - mInitialScrollP;
@@ -192,7 +202,7 @@ public class TaskStackViewLayoutAlgorithm {
float scaleAtP = curveProgressToScale(progress);
int scaleYOffsetAtP = (int) (((1f - scaleAtP) * taskHeight) / 2);
int screenY = curveProgressToScreenY(progress) + scaleYOffsetAtP;
boolean hasVisibleThumbnail = (prevScreenY - screenY) > mConfig.taskBarHeight;
boolean hasVisibleThumbnail = (prevScreenY - screenY) > taskBarHeight;
if (hasVisibleThumbnail) {
numVisibleThumbnails++;
numVisibleTasks++;
@@ -251,8 +261,8 @@ public class TaskStackViewLayoutAlgorithm {
}
float scale = curveProgressToScale(pBounded);
int scaleYOffset = (int) (((1f - scale) * mTaskRect.height()) / 2);
int minZ = mConfig.taskViewTranslationZMinPx;
int maxZ = mConfig.taskViewTranslationZMaxPx;
int minZ = mContext.getResources().getDimensionPixelSize(R.dimen.recents_task_view_z_min);
int maxZ = mContext.getResources().getDimensionPixelSize(R.dimen.recents_task_view_z_max);
transformOut.scale = scale;
transformOut.translationY = curveProgressToScreenY(pBounded) - mStackVisibleRect.top -
scaleYOffset;

View File

@@ -21,9 +21,11 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.OverScroller;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.R;
/* The scrolling logic for a TaskStackView */
public class TaskStackViewScroller {
@@ -31,7 +33,7 @@ public class TaskStackViewScroller {
public void onScrollChanged(float p);
}
RecentsConfiguration mConfig;
Context mContext;
TaskStackViewLayoutAlgorithm mLayoutAlgorithm;
TaskStackViewScrollerCallbacks mCb;
@@ -41,10 +43,14 @@ public class TaskStackViewScroller {
ObjectAnimator mScrollAnimator;
float mFinalAnimatedScroll;
public TaskStackViewScroller(Context context, RecentsConfiguration config, TaskStackViewLayoutAlgorithm layoutAlgorithm) {
mConfig = config;
Interpolator mLinearOutSlowInInterpolator;
public TaskStackViewScroller(Context context, TaskStackViewLayoutAlgorithm layoutAlgorithm) {
mContext = context;
mScroller = new OverScroller(context);
mLayoutAlgorithm = layoutAlgorithm;
mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.linear_out_slow_in);
setStackScroll(getStackScroll());
}
@@ -140,8 +146,9 @@ public class TaskStackViewScroller {
mFinalAnimatedScroll = newScroll;
mScrollAnimator = ObjectAnimator.ofFloat(this, "stackScroll", curScroll, newScroll);
mScrollAnimator.setDuration(mConfig.taskStackScrollDuration);
mScrollAnimator.setInterpolator(mConfig.linearOutSlowInInterpolator);
mScrollAnimator.setDuration(mContext.getResources().getInteger(
R.integer.recents_animate_task_stack_scroll_duration));
mScrollAnimator.setInterpolator(mLinearOutSlowInInterpolator);
mScrollAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {

View File

@@ -26,7 +26,7 @@ import android.view.ViewParent;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.R;
import java.util.List;
@@ -34,7 +34,7 @@ import java.util.List;
class TaskStackViewTouchHandler implements SwipeHelper.Callback {
static int INACTIVE_POINTER_ID = -1;
RecentsConfiguration mConfig;
Context mContext;
TaskStackView mSv;
TaskStackViewScroller mScroller;
VelocityTracker mVelocityTracker;
@@ -62,7 +62,8 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
boolean mInterceptedBySwipeHelper;
public TaskStackViewTouchHandler(Context context, TaskStackView sv,
RecentsConfiguration config, TaskStackViewScroller scroller) {
TaskStackViewScroller scroller) {
mContext = context;
ViewConfiguration configuration = ViewConfiguration.get(context);
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
@@ -71,10 +72,9 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
mWindowTouchSlop = configuration.getScaledWindowTouchSlop();
mSv = sv;
mScroller = scroller;
mConfig = config;
float densityScale = context.getResources().getDisplayMetrics().density;
mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, mPagingTouchSlop);
mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, densityScale, mPagingTouchSlop);
mSwipeHelper.setMinAlpha(1f);
}
@@ -268,7 +268,8 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
if (Float.compare(overScrollAmount, 0f) != 0) {
// Bound the overscroll to a fixed amount, and inversely scale the y-movement
// relative to how close we are to the max overscroll
float maxOverScroll = mConfig.taskStackOverscrollPct;
float maxOverScroll = mContext.getResources().getFloat(
R.dimen.recents_stack_overscroll_percentage);
deltaP *= (1f - (Math.min(maxOverScroll, overScrollAmount)
/ maxOverScroll));
}

View File

@@ -20,16 +20,25 @@ import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.*;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.accessibility.AccessibilityManager;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
import com.android.systemui.R;
import com.android.systemui.recents.Constants;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
@@ -75,6 +84,10 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
View mActionButtonView;
TaskViewCallbacks mCb;
Interpolator mFastOutSlowInInterpolator;
Interpolator mFastOutLinearInInterpolator;
Interpolator mQuintOutInterpolator;
// Optimizations
ValueAnimator.AnimatorUpdateListener mUpdateDimListener =
new ValueAnimator.AnimatorUpdateListener() {
@@ -99,14 +112,22 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
public TaskView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
Resources res = context.getResources();
mConfig = RecentsConfiguration.getInstance();
mMaxDimScale = mConfig.taskStackMaxDim / 255f;
mMaxDimScale = res.getInteger(R.integer.recents_max_task_stack_view_dim) / 255f;
mClipViewInStack = true;
mViewBounds = new AnimateableViewBounds(this, mConfig.taskViewRoundedCornerRadiusPx);
mViewBounds = new AnimateableViewBounds(this, res.getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius));
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_linear_in);
mQuintOutInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.decelerate_quint);
setTaskProgress(getTaskProgress());
setDim(getDim());
if (mConfig.fakeShadows) {
setBackground(new FakeShadowDrawable(context.getResources(), mConfig));
setBackground(new FakeShadowDrawable(res, mConfig));
}
setOutlineProvider(mViewBounds);
}
@@ -159,6 +180,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
int widthWithoutPadding = width - mPaddingLeft - mPaddingRight;
int heightWithoutPadding = height - mPaddingTop - mPaddingBottom;
int taskBarHeight = getResources().getDimensionPixelSize(R.dimen.recents_task_bar_height);
// Measure the content
mContent.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
@@ -166,7 +188,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
// Measure the bar view, and action button
mHeaderView.measure(MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mConfig.taskBarHeight, MeasureSpec.EXACTLY));
MeasureSpec.makeMeasureSpec(taskBarHeight, MeasureSpec.EXACTLY));
mActionButtonView.measure(
MeasureSpec.makeMeasureSpec(widthWithoutPadding, MeasureSpec.AT_MOST),
MeasureSpec.makeMeasureSpec(heightWithoutPadding, MeasureSpec.AT_MOST));
@@ -186,7 +208,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
void updateViewPropertiesToTaskTransform(TaskViewTransform toTransform, int duration,
ValueAnimator.AnimatorUpdateListener updateCallback) {
// Apply the transform
toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator, false,
toTransform.applyToTaskView(this, duration, mFastOutSlowInInterpolator, false,
!mConfig.fakeShadows, updateCallback);
// Update the task progress
@@ -238,10 +260,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
* first layout because the actual animation into recents may take a long time. */
void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask,
boolean occludesLaunchTarget, int offscreenY) {
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
int initialDim = getDim();
if (mConfig.launchedHasConfigurationChanged) {
if (launchState.launchedHasConfigurationChanged) {
// Just load the views as-is
} else if (mConfig.launchedFromAppWithThumbnail) {
} else if (launchState.launchedFromAppWithThumbnail) {
if (isTaskViewLaunchTargetTask) {
// Set the dim to 0 so we can animate it in
initialDim = 0;
@@ -252,7 +275,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
setTranslationY(offscreenY);
}
} else if (mConfig.launchedFromHome) {
} else if (launchState.launchedFromHome) {
// Move the task view off screen (below) so we can animate it in
setTranslationY(offscreenY);
setTranslationZ(0);
@@ -267,45 +290,59 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Animates this task view as it enters recents */
void startEnterRecentsAnimation(final ViewAnimation.TaskViewEnterContext ctx) {
RecentsActivityLaunchState launchState = mConfig.getLaunchState();
Resources res = mContext.getResources();
final TaskViewTransform transform = ctx.currentTaskTransform;
final int transitionEnterFromAppDelay = res.getInteger(
R.integer.recents_enter_from_app_transition_duration);
final int transitionEnterFromHomeDelay = res.getInteger(
R.integer.recents_enter_from_home_transition_duration);
final int taskViewEnterFromAppDuration = res.getInteger(
R.integer.recents_task_enter_from_app_duration);
final int taskViewEnterFromHomeDuration = res.getInteger(
R.integer.recents_task_enter_from_home_duration);
final int taskViewEnterFromHomeStaggerDelay = res.getInteger(
R.integer.recents_task_enter_from_home_stagger_delay);
final int taskViewAffiliateGroupEnterOffset = res.getDimensionPixelSize(
R.dimen.recents_task_view_affiliate_group_enter_offset);
int startDelay = 0;
if (mConfig.launchedFromAppWithThumbnail) {
if (launchState.launchedFromAppWithThumbnail) {
if (mTask.isLaunchTarget) {
// Animate the dim/overlay
if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
// Animate the thumbnail alpha before the dim animation (to prevent updating the
// hardware layer)
mThumbnailView.startEnterRecentsAnimation(mConfig.transitionEnterFromAppDelay,
mThumbnailView.startEnterRecentsAnimation(transitionEnterFromAppDelay,
new Runnable() {
@Override
public void run() {
animateDimToProgress(0, mConfig.taskViewEnterFromAppDuration,
animateDimToProgress(0, taskViewEnterFromAppDuration,
ctx.postAnimationTrigger.decrementOnAnimationEnd());
}
});
} else {
// Immediately start the dim animation
animateDimToProgress(mConfig.transitionEnterFromAppDelay,
mConfig.taskViewEnterFromAppDuration,
animateDimToProgress(transitionEnterFromAppDelay,
taskViewEnterFromAppDuration,
ctx.postAnimationTrigger.decrementOnAnimationEnd());
}
ctx.postAnimationTrigger.increment();
// Animate the action button in
fadeInActionButton(mConfig.transitionEnterFromAppDelay,
mConfig.taskViewEnterFromAppDuration);
fadeInActionButton(transitionEnterFromAppDelay,
taskViewEnterFromAppDuration);
} else {
// Animate the task up if it was occluding the launch target
if (ctx.currentTaskOccludesLaunchTarget) {
setTranslationY(transform.translationY + mConfig.taskViewAffiliateGroupEnterOffsetPx);
setTranslationY(transform.translationY + taskViewAffiliateGroupEnterOffset);
setAlpha(0f);
animate().alpha(1f)
.translationY(transform.translationY)
.setStartDelay(mConfig.transitionEnterFromAppDelay)
.setStartDelay(transitionEnterFromAppDelay)
.setUpdateListener(null)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(mConfig.taskViewEnterFromHomeDuration)
.setInterpolator(mFastOutSlowInInterpolator)
.setDuration(taskViewEnterFromHomeDuration)
.withEndAction(new Runnable() {
@Override
public void run() {
@@ -317,13 +354,13 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
ctx.postAnimationTrigger.increment();
}
}
startDelay = mConfig.transitionEnterFromAppDelay;
startDelay = transitionEnterFromAppDelay;
} else if (mConfig.launchedFromHome) {
} else if (launchState.launchedFromHome) {
// Animate the tasks up
int frontIndex = (ctx.currentStackViewCount - ctx.currentStackViewIndex - 1);
int delay = mConfig.transitionEnterFromHomeDelay +
frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay;
int delay = transitionEnterFromHomeDelay +
frontIndex * taskViewEnterFromHomeStaggerDelay;
setScaleX(transform.scale);
setScaleY(transform.scale);
@@ -334,9 +371,9 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
.translationY(transform.translationY)
.setStartDelay(delay)
.setUpdateListener(ctx.updateListener)
.setInterpolator(mConfig.quintOutInterpolator)
.setDuration(mConfig.taskViewEnterFromHomeDuration +
frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay)
.setInterpolator(mQuintOutInterpolator)
.setDuration(taskViewEnterFromHomeDuration +
frontIndex * taskViewEnterFromHomeStaggerDelay)
.withEndAction(new Runnable() {
@Override
public void run() {
@@ -373,12 +410,14 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Animates this task view as it leaves recents by pressing home. */
void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
int taskViewExitToHomeDuration = getResources().getInteger(
R.integer.recents_task_exit_to_home_duration);
animate()
.translationY(ctx.offscreenTranslationY)
.setStartDelay(0)
.setUpdateListener(null)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
.setDuration(mConfig.taskViewExitToHomeDuration)
.setInterpolator(mFastOutLinearInInterpolator)
.setDuration(taskViewExitToHomeDuration)
.withEndAction(ctx.postAnimationTrigger.decrementAsRunnable())
.start();
ctx.postAnimationTrigger.increment();
@@ -392,6 +431,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Animates this task view as it exits recents */
void startLaunchTaskAnimation(final Runnable postAnimRunnable, boolean isLaunchingTask,
boolean occludesLaunchTarget, boolean lockToTask) {
final int taskViewExitToAppDuration = mContext.getResources().getInteger(
R.integer.recents_task_exit_to_app_duration);
final int taskViewAffiliateGroupEnterOffset = mContext.getResources().getDimensionPixelSize(
R.dimen.recents_task_view_affiliate_group_enter_offset);
if (isLaunchingTask) {
// Animate the thumbnail alpha back into full opacity for the window animation out
mThumbnailView.startLaunchTaskAnimation(postAnimRunnable);
@@ -399,8 +443,8 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
// Animate the dim
if (mDimAlpha > 0) {
ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
anim.setDuration(mConfig.taskViewExitToAppDuration);
anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
anim.setDuration(taskViewExitToAppDuration);
anim.setInterpolator(mFastOutLinearInInterpolator);
anim.start();
}
@@ -414,8 +458,8 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
mActionButtonView.animate()
.alpha(0f)
.setStartDelay(0)
.setDuration(mConfig.taskViewExitToAppDuration)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
.setDuration(taskViewExitToAppDuration)
.setInterpolator(mFastOutLinearInInterpolator)
.start();
} else {
// Hide the dismiss button
@@ -424,11 +468,11 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
// animate it away first
if (occludesLaunchTarget) {
animate().alpha(0f)
.translationY(getTranslationY() + mConfig.taskViewAffiliateGroupEnterOffsetPx)
.translationY(getTranslationY() + taskViewAffiliateGroupEnterOffset)
.setStartDelay(0)
.setUpdateListener(null)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
.setDuration(mConfig.taskViewExitToAppDuration)
.setInterpolator(mFastOutLinearInInterpolator)
.setDuration(taskViewExitToAppDuration)
.start();
}
}
@@ -436,15 +480,20 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks,
/** Animates the deletion of this task view */
void startDeleteTaskAnimation(final Runnable r, int delay) {
int taskViewRemoveAnimDuration = getResources().getInteger(
R.integer.recents_animate_task_view_remove_duration);
int taskViewRemoveAnimTranslationXPx = getResources().getDimensionPixelSize(
R.dimen.recents_task_view_remove_anim_translation_x);
// Disabling clipping with the stack while the view is animating away
setClipViewInStack(false);
animate().translationX(mConfig.taskViewRemoveAnimTranslationXPx)
animate().translationX(taskViewRemoveAnimTranslationXPx)
.alpha(0f)
.setStartDelay(delay)
.setUpdateListener(null)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(mConfig.taskViewRemoveAnimDuration)
.setInterpolator(mFastOutSlowInInterpolator)
.setDuration(taskViewRemoveAnimDuration)
.withEndAction(new Runnable() {
@Override
public void run() {

View File

@@ -26,19 +26,21 @@ import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewOutlineProvider;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
@@ -67,6 +69,8 @@ public class TaskViewHeader extends FrameLayout {
boolean mCurrentPrimaryColorIsDark;
int mCurrentPrimaryColor;
int mBackgroundColor;
int mCornerRadius;
int mHighlightHeight;
Drawable mLightDismissDrawable;
Drawable mDarkDismissDrawable;
RippleDrawable mBackground;
@@ -81,6 +85,9 @@ public class TaskViewHeader extends FrameLayout {
Paint mDimLayerPaint = new Paint();
PorterDuffColorFilter mDimColorFilter = new PorterDuffColorFilter(0, PorterDuff.Mode.SRC_ATOP);
Interpolator mFastOutSlowInInterpolator;
Interpolator mFastOutLinearInInterpolator;
boolean mLayersDisabled;
public TaskViewHeader(Context context) {
@@ -113,13 +120,21 @@ public class TaskViewHeader extends FrameLayout {
mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
mDismissContentDescription =
context.getString(R.string.accessibility_recents_item_will_be_dismissed);
mCornerRadius = getResources().getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
mHighlightHeight = getResources().getDimensionPixelSize(
R.dimen.recents_task_view_highlight);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_linear_in);
// Configure the highlight paint
if (sHighlightPaint == null) {
sHighlightPaint = new Paint();
sHighlightPaint.setStyle(Paint.Style.STROKE);
sHighlightPaint.setStrokeWidth(mConfig.taskViewHighlightPx);
sHighlightPaint.setColor(mConfig.taskBarViewHighlightColor);
sHighlightPaint.setStrokeWidth(mHighlightHeight);
sHighlightPaint.setColor(context.getColor(R.color.recents_task_bar_highlight_color));
sHighlightPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
sHighlightPaint.setAntiAlias(true);
}
@@ -154,8 +169,8 @@ public class TaskViewHeader extends FrameLayout {
@Override
protected void onDraw(Canvas canvas) {
// Draw the highlight at the top edge (but put the bottom edge just out of view)
float offset = (float) Math.ceil(mConfig.taskViewHighlightPx / 2f);
float radius = mConfig.taskViewRoundedCornerRadiusPx;
float offset = (float) Math.ceil(mHighlightHeight / 2f);
float radius = mCornerRadius;
int count = canvas.save(Canvas.CLIP_SAVE_FLAG);
canvas.clipRect(0, 0, getMeasuredWidth(), getMeasuredHeight());
canvas.drawRoundRect(-offset, 0f, (float) getMeasuredWidth() + offset,
@@ -207,10 +222,15 @@ public class TaskViewHeader extends FrameLayout {
mBackgroundColorDrawable.setColor(t.colorPrimary);
mBackgroundColor = t.colorPrimary;
}
int taskBarViewLightTextColor = getResources().getColor(
R.color.recents_task_bar_light_text_color);
int taskBarViewDarkTextColor = getResources().getColor(
R.color.recents_task_bar_dark_text_color);
mCurrentPrimaryColor = t.colorPrimary;
mCurrentPrimaryColorIsDark = t.useLightOnPrimaryColor;
mActivityDescription.setTextColor(t.useLightOnPrimaryColor ?
mConfig.taskBarViewLightTextColor : mConfig.taskBarViewDarkTextColor);
taskBarViewLightTextColor : taskBarViewDarkTextColor);
mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
mLightDismissDrawable : mDarkDismissDrawable);
mDismissButton.setContentDescription(String.format(mDismissContentDescription,
@@ -262,12 +282,14 @@ public class TaskViewHeader extends FrameLayout {
/** Animates this task bar dismiss button when launching a task. */
void startLaunchTaskDismissAnimation() {
if (mDismissButton.getVisibility() == View.VISIBLE) {
int taskViewExitToAppDuration = mContext.getResources().getInteger(
R.integer.recents_task_exit_to_app_duration);
mDismissButton.animate().cancel();
mDismissButton.animate()
.alpha(0f)
.setStartDelay(0)
.setInterpolator(mConfig.fastOutSlowInInterpolator)
.setDuration(mConfig.taskViewExitToAppDuration)
.setInterpolator(mFastOutSlowInInterpolator)
.setDuration(taskViewExitToAppDuration)
.start();
}
}
@@ -280,8 +302,9 @@ public class TaskViewHeader extends FrameLayout {
mDismissButton.animate()
.alpha(1f)
.setStartDelay(0)
.setInterpolator(mConfig.fastOutLinearInInterpolator)
.setDuration(mConfig.taskViewEnterFromAppDuration)
.setInterpolator(mFastOutLinearInInterpolator)
.setDuration(getResources().getInteger(
R.integer.recents_task_enter_from_app_duration))
.start();
}
}

View File

@@ -32,9 +32,11 @@ import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;
import com.android.systemui.recents.RecentsConfiguration;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.R;
/**
@@ -43,9 +45,8 @@ import com.android.systemui.recents.model.Task;
*/
public class TaskViewThumbnail extends View {
RecentsConfiguration mConfig;
// Drawing
int mCornerRadius;
float mDimAlpha;
Matrix mScaleMatrix = new Matrix();
Paint mDrawPaint = new Paint();
@@ -54,6 +55,8 @@ public class TaskViewThumbnail extends View {
BitmapShader mBitmapShader;
LightingColorFilter mLightingColorFilter = new LightingColorFilter(0xffffffff, 0);
Interpolator mFastOutSlowInInterpolator;
// Thumbnail alpha
float mThumbnailAlpha;
ValueAnimator mThumbnailAlphaAnimator;
@@ -89,15 +92,18 @@ public class TaskViewThumbnail extends View {
public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mConfig = RecentsConfiguration.getInstance();
mDrawPaint.setColorFilter(mLightingColorFilter);
mDrawPaint.setFilterBitmap(true);
mDrawPaint.setAntiAlias(true);
mCornerRadius = getResources().getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
}
@Override
protected void onFinishInflate() {
mThumbnailAlpha = mConfig.taskViewThumbnailAlpha;
mThumbnailAlpha = getResources().getFloat(R.dimen.recents_task_view_thumbnail_alpha);
updateThumbnailPaintFilter();
}
@@ -117,8 +123,8 @@ public class TaskViewThumbnail extends View {
}
// Draw the thumbnail with the rounded corners
canvas.drawRoundRect(0, 0, getWidth(), getHeight(),
mConfig.taskViewRoundedCornerRadiusPx,
mConfig.taskViewRoundedCornerRadiusPx, mDrawPaint);
mCornerRadius,
mCornerRadius, mDrawPaint);
}
/** Sets the thumbnail to a given bitmap. */
@@ -215,8 +221,10 @@ public class TaskViewThumbnail extends View {
startFadeAnimation(1f, 0, 150, null);
}
} else {
if (Float.compare(getAlpha(), mConfig.taskViewThumbnailAlpha) != 0) {
startFadeAnimation(mConfig.taskViewThumbnailAlpha, 0, 150, null);
float taskViewThumbnailAlpha = getResources().getFloat(
R.dimen.recents_task_view_thumbnail_alpha);
if (Float.compare(getAlpha(), taskViewThumbnailAlpha) != 0) {
startFadeAnimation(taskViewThumbnailAlpha, 0, 150, null);
}
}
}
@@ -229,20 +237,26 @@ public class TaskViewThumbnail extends View {
if (isTaskViewLaunchTargetTask) {
mThumbnailAlpha = 1f;
} else {
mThumbnailAlpha = mConfig.taskViewThumbnailAlpha;
mThumbnailAlpha = getResources().getFloat(
R.dimen.recents_task_view_thumbnail_alpha);
}
updateThumbnailPaintFilter();
}
/** Animates this task thumbnail as it enters Recents. */
void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
startFadeAnimation(mConfig.taskViewThumbnailAlpha, delay,
mConfig.taskViewEnterFromAppDuration, postAnimRunnable);
float taskViewThumbnailAlpha = getResources().getFloat(
R.dimen.recents_task_view_thumbnail_alpha);
startFadeAnimation(taskViewThumbnailAlpha, delay,
getResources().getInteger(R.integer.recents_task_enter_from_app_duration),
postAnimRunnable);
}
/** Animates this task thumbnail as it exits Recents. */
void startLaunchTaskAnimation(Runnable postAnimRunnable) {
startFadeAnimation(1f, 0, mConfig.taskViewExitToAppDuration, postAnimRunnable);
int taskViewExitToAppDuration = mContext.getResources().getInteger(
R.integer.recents_task_exit_to_app_duration);
startFadeAnimation(1f, 0, taskViewExitToAppDuration, postAnimRunnable);
}
/** Starts a new thumbnail alpha animation. */
@@ -251,7 +265,7 @@ public class TaskViewThumbnail extends View {
mThumbnailAlphaAnimator = ValueAnimator.ofFloat(mThumbnailAlpha, finalAlpha);
mThumbnailAlphaAnimator.setStartDelay(delay);
mThumbnailAlphaAnimator.setDuration(duration);
mThumbnailAlphaAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
mThumbnailAlphaAnimator.setInterpolator(mFastOutSlowInInterpolator);
mThumbnailAlphaAnimator.addUpdateListener(mThumbnailAlphaUpdateListener);
if (postAnimRunnable != null) {
mThumbnailAlphaAnimator.addListener(new AnimatorListenerAdapter() {