Merge "Refactoring to single path for overview mode." into ub-launcher3-burnaby

This commit is contained in:
Winson Chung
2015-04-21 23:52:07 +00:00
committed by Android (Google) Code Review
9 changed files with 653 additions and 621 deletions
-4
View File
@@ -6,10 +6,6 @@
<!-- Out of 100, the percent to shrink the workspace during spring loaded mode. --> <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
<integer name="config_workspaceSpringLoadShrinkPercentage">90</integer> <integer name="config_workspaceSpringLoadShrinkPercentage">90</integer>
<!-- Workspace -->
<!-- Whether or not the drop targets drop down as opposed to fade in -->
<bool name="config_useDropTargetDownTransition">false</bool>
<!-- Hotseat --> <!-- Hotseat -->
<bool name="hotseat_transpose_layout_with_orientation">false</bool> <bool name="hotseat_transpose_layout_with_orientation">false</bool>
</resources> </resources>
+1 -4
View File
@@ -27,7 +27,7 @@
<!-- AllApps/Customize/AppsCustomize --> <!-- AllApps/Customize/AppsCustomize -->
<!-- The alpha of the AppsCustomize bg in spring loaded mode --> <!-- The alpha of the AppsCustomize bg in spring loaded mode -->
<integer name="config_workspaceScrimAlpha">55</integer> <integer name="config_workspaceScrimAlpha">55</integer>
<integer name="config_workspaceUnshrinkTime">300</integer> <integer name="config_workspaceUnshrinkTime">100</integer>
<integer name="config_overviewTransitionTime">250</integer> <integer name="config_overviewTransitionTime">250</integer>
<!-- Out of 100, the percent to shrink the workspace during spring loaded mode. --> <!-- Out of 100, the percent to shrink the workspace during spring loaded mode. -->
@@ -55,9 +55,6 @@
<integer name="config_appsCustomizeDragSlopeThreshold">150</integer> <integer name="config_appsCustomizeDragSlopeThreshold">150</integer>
<!-- Workspace --> <!-- Workspace -->
<!-- Whether or not the drop targets drop down as opposed to fade in -->
<bool name="config_useDropTargetDownTransition">false</bool>
<!-- The transition duration for the background of the drop targets --> <!-- The transition duration for the background of the drop targets -->
<integer name="config_dropTargetBgTransitionDuration">0</integer> <integer name="config_dropTargetBgTransitionDuration">0</integer>
+28 -14
View File
@@ -214,7 +214,6 @@ public class Launcher extends Activity
/** The different states that Launcher can be in. */ /** The different states that Launcher can be in. */
enum State { NONE, WORKSPACE, APPS, APPS_SPRING_LOADED, WIDGETS, WIDGETS_SPRING_LOADED }; enum State { NONE, WORKSPACE, APPS, APPS_SPRING_LOADED, WIDGETS, WIDGETS_SPRING_LOADED };
@Thunk State mState = State.WORKSPACE; @Thunk State mState = State.WORKSPACE;
@Thunk AnimatorSet mStateAnimation;
@Thunk LauncherStateTransitionAnimation mStateTransitionAnimation; @Thunk LauncherStateTransitionAnimation mStateTransitionAnimation;
private boolean mIsSafeModeEnabled; private boolean mIsSafeModeEnabled;
@@ -528,7 +527,8 @@ public class Launcher extends Activity
@Override @Override
public void dismissAllApps() { public void dismissAllApps() {
showWorkspace(true); showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, true, null,
false /* notifyLauncherCallbacks */);
} }
}); });
return true; return true;
@@ -785,7 +785,7 @@ public class Launcher extends Activity
return; return;
} else if (requestCode == REQUEST_PICK_WALLPAPER) { } else if (requestCode == REQUEST_PICK_WALLPAPER) {
if (resultCode == RESULT_OK && mWorkspace.isInOverviewMode()) { if (resultCode == RESULT_OK && mWorkspace.isInOverviewMode()) {
mWorkspace.exitOverviewMode(false); showWorkspace(false);
} }
return; return;
} }
@@ -1220,7 +1220,6 @@ public class Launcher extends Activity
return false; return false;
} }
public void addToCustomContentPage(View customContent, public void addToCustomContentPage(View customContent,
CustomContentCallbacks callbacks, String description) { CustomContentCallbacks callbacks, String description) {
mWorkspace.addToCustomContentPage(customContent, callbacks, description); mWorkspace.addToCustomContentPage(customContent, callbacks, description);
@@ -2480,7 +2479,7 @@ public class Launcher extends Activity
} else if (isWidgetsViewVisible()) { } else if (isWidgetsViewVisible()) {
showOverviewMode(true); showOverviewMode(true);
} else if (mWorkspace.isInOverviewMode()) { } else if (mWorkspace.isInOverviewMode()) {
mWorkspace.exitOverviewMode(true); showWorkspace(true);
} else if (mWorkspace.getOpenFolder() != null) { } else if (mWorkspace.getOpenFolder() != null) {
Folder openFolder = mWorkspace.getOpenFolder(); Folder openFolder = mWorkspace.getOpenFolder();
if (openFolder.isEditingName()) { if (openFolder.isEditingName()) {
@@ -2523,14 +2522,14 @@ public class Launcher extends Activity
if (v instanceof Workspace) { if (v instanceof Workspace) {
if (mWorkspace.isInOverviewMode()) { if (mWorkspace.isInOverviewMode()) {
mWorkspace.exitOverviewMode(true); showWorkspace(true);
} }
return; return;
} }
if (v instanceof CellLayout) { if (v instanceof CellLayout) {
if (mWorkspace.isInOverviewMode()) { if (mWorkspace.isInOverviewMode()) {
mWorkspace.exitOverviewMode(mWorkspace.indexOfChild(v), true); showWorkspace(mWorkspace.indexOfChild(v), true);
} }
} }
@@ -3178,7 +3177,9 @@ public class Launcher extends Activity
if (v instanceof Workspace) { if (v instanceof Workspace) {
if (!mWorkspace.isInOverviewMode()) { if (!mWorkspace.isInOverviewMode()) {
if (mWorkspace.enterOverviewMode()) {
if (!mWorkspace.isTouchActive()) {
showOverviewMode(true);
mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, mWorkspace.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
return true; return true;
@@ -3211,7 +3212,7 @@ public class Launcher extends Activity
if (mWorkspace.isInOverviewMode()) { if (mWorkspace.isInOverviewMode()) {
mWorkspace.startReordering(v); mWorkspace.startReordering(v);
} else { } else {
mWorkspace.enterOverviewMode(); showOverviewMode(true);
} }
} else { } else {
final boolean isAllAppsButton = inHotseat && isAllAppsButtonRank( final boolean isAllAppsButton = inHotseat && isAllAppsButtonRank(
@@ -3302,17 +3303,28 @@ public class Launcher extends Activity
} }
protected void showWorkspace(boolean animated) { protected void showWorkspace(boolean animated) {
showWorkspace(animated, null); showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated, null,
true);
} }
void showWorkspace(boolean animated, Runnable onCompleteRunnable) { protected void showWorkspace(boolean animated, Runnable onCompleteRunnable) {
showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated,
onCompleteRunnable, true);
}
protected void showWorkspace(int snapToPage, boolean animated) {
showWorkspace(snapToPage, animated, null, true);
}
void showWorkspace(int snapToPage, boolean animated, Runnable onCompleteRunnable,
boolean notifyLauncherCallbacks) {
boolean changed = mState != State.WORKSPACE || boolean changed = mState != State.WORKSPACE ||
mWorkspace.getState() != Workspace.State.NORMAL; mWorkspace.getState() != Workspace.State.NORMAL;
if (changed) { if (changed) {
boolean wasInSpringLoadedMode = (mState != State.WORKSPACE); boolean wasInSpringLoadedMode = (mState != State.WORKSPACE);
mWorkspace.setVisibility(View.VISIBLE); mWorkspace.setVisibility(View.VISIBLE);
mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.NORMAL, mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.NORMAL,
animated, onCompleteRunnable); snapToPage, animated, onCompleteRunnable);
// Show the search bar (only animate if we were showing the drop target bar in spring // Show the search bar (only animate if we were showing the drop target bar in spring
// loaded mode) // loaded mode)
@@ -3345,7 +3357,8 @@ public class Launcher extends Activity
void showOverviewMode(boolean animated) { void showOverviewMode(boolean animated) {
mWorkspace.setVisibility(View.VISIBLE); mWorkspace.setVisibility(View.VISIBLE);
mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.OVERVIEW, mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.OVERVIEW,
animated, null /* onCompleteRunnable */); WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated,
null /* onCompleteRunnable */);
mState = State.WORKSPACE; mState = State.WORKSPACE;
onWorkspaceShown(animated); onWorkspaceShown(animated);
} }
@@ -3419,7 +3432,8 @@ public class Launcher extends Activity
} }
mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.SPRING_LOADED, mStateTransitionAnimation.startAnimationToWorkspace(mState, Workspace.State.SPRING_LOADED,
true /* animated */, null /* onCompleteRunnable */); WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, true /* animated */,
null /* onCompleteRunnable */);
mState = isAppsViewVisible() ? State.APPS_SPRING_LOADED : State.WIDGETS_SPRING_LOADED; mState = isAppsViewVisible() ? State.APPS_SPRING_LOADED : State.WIDGETS_SPRING_LOADED;
} }
@@ -126,7 +126,7 @@ class LauncherClings implements OnClickListener {
@Override @Override
public boolean onLongClick(View v) { public boolean onLongClick(View v) {
mLauncher.getWorkspace().enterOverviewMode(); mLauncher.showOverviewMode(true);
dismissLongPressCling(); dismissLongPressCling();
return true; return true;
} }
@@ -23,7 +23,6 @@ import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder; import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator; import android.animation.TimeInterpolator;
import android.content.res.Resources; import android.content.res.Resources;
import android.support.v7.widget.RecyclerView;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.ViewAnimationUtils; import android.view.ViewAnimationUtils;
@@ -174,7 +173,8 @@ public class LauncherStateTransitionAnimation {
} }
}; };
startAnimationToOverlay(Workspace.State.NORMAL_HIDDEN, toView, toView.getContentView(), startAnimationToOverlay(Workspace.State.NORMAL_HIDDEN, toView, toView.getContentView(),
toView.getRevealView(), animated, false /* hideSearchBar */, cb); toView.getRevealView(), animated,
!mLauncher.isAllAppsSearchOverridden() /* hideSearchBar */, cb);
} }
/** /**
@@ -207,8 +207,8 @@ public class LauncherStateTransitionAnimation {
* Starts and animation to the workspace from the current overlay view. * Starts and animation to the workspace from the current overlay view.
*/ */
public void startAnimationToWorkspace(final Launcher.State fromState, public void startAnimationToWorkspace(final Launcher.State fromState,
final Workspace.State toWorkspaceState, final boolean animated, final Workspace.State toWorkspaceState, final int toWorkspacePage,
final Runnable onCompleteRunnable) { final boolean animated, final Runnable onCompleteRunnable) {
if (toWorkspaceState != Workspace.State.NORMAL && if (toWorkspaceState != Workspace.State.NORMAL &&
toWorkspaceState != Workspace.State.SPRING_LOADED && toWorkspaceState != Workspace.State.SPRING_LOADED &&
toWorkspaceState != Workspace.State.OVERVIEW) { toWorkspaceState != Workspace.State.OVERVIEW) {
@@ -216,11 +216,11 @@ public class LauncherStateTransitionAnimation {
} }
if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED) { if (fromState == Launcher.State.APPS || fromState == Launcher.State.APPS_SPRING_LOADED) {
startAnimationToWorkspaceFromAllApps(fromState, toWorkspaceState, animated, startAnimationToWorkspaceFromAllApps(fromState, toWorkspaceState, toWorkspacePage,
onCompleteRunnable); animated, onCompleteRunnable);
} else { } else {
startAnimationToWorkspaceFromWidgets(fromState, toWorkspaceState, animated, startAnimationToWorkspaceFromWidgets(fromState, toWorkspaceState, toWorkspacePage,
onCompleteRunnable); animated, onCompleteRunnable);
} }
} }
@@ -249,8 +249,8 @@ public class LauncherStateTransitionAnimation {
// Create the workspace animation. // Create the workspace animation.
// NOTE: this call apparently also sets the state for the workspace if !animated // NOTE: this call apparently also sets the state for the workspace if !animated
Animator workspaceAnim = mLauncher.getWorkspace().getChangeStateAnimation( Animator workspaceAnim = mLauncher.getWorkspace().setStateWithAnimation(
toWorkspaceState, animated, layerViews); toWorkspaceState, -1, animated, layerViews);
if (animated && initialized) { if (animated && initialized) {
mStateAnimation = LauncherAnimUtils.createAnimatorSet(); mStateAnimation = LauncherAnimUtils.createAnimatorSet();
@@ -424,8 +424,8 @@ public class LauncherStateTransitionAnimation {
* Starts and animation to the workspace from the apps view. * Starts and animation to the workspace from the apps view.
*/ */
private void startAnimationToWorkspaceFromAllApps(final Launcher.State fromState, private void startAnimationToWorkspaceFromAllApps(final Launcher.State fromState,
final Workspace.State toWorkspaceState, final boolean animated, final Workspace.State toWorkspaceState, final int toWorkspacePage,
final Runnable onCompleteRunnable) { final boolean animated, final Runnable onCompleteRunnable) {
AppsContainerView appsView = mLauncher.getAppsView(); AppsContainerView appsView = mLauncher.getAppsView();
PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() { PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
int[] mAllAppsToPanelDelta; int[] mAllAppsToPanelDelta;
@@ -477,16 +477,17 @@ public class LauncherStateTransitionAnimation {
}; };
} }
}; };
startAnimationToWorkspaceFromOverlay(toWorkspaceState, appsView, appsView.getContentView(), startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage, appsView,
appsView.getRevealView(), animated, onCompleteRunnable, cb); appsView.getContentView(), appsView.getRevealView(), animated, onCompleteRunnable,
cb);
} }
/** /**
* Starts and animation to the workspace from the widgets view. * Starts and animation to the workspace from the widgets view.
*/ */
private void startAnimationToWorkspaceFromWidgets(final Launcher.State fromState, private void startAnimationToWorkspaceFromWidgets(final Launcher.State fromState,
final Workspace.State toWorkspaceState, final boolean animated, final Workspace.State toWorkspaceState, final int toWorkspacePage,
final Runnable onCompleteRunnable) { final boolean animated, final Runnable onCompleteRunnable) {
final WidgetsContainerView widgetsView = mLauncher.getWidgetsView(); final WidgetsContainerView widgetsView = mLauncher.getWidgetsView();
final Resources res = mLauncher.getResources(); final Resources res = mLauncher.getResources();
PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() { PrivateTransitionCallbacks cb = new PrivateTransitionCallbacks() {
@@ -514,7 +515,7 @@ public class LauncherStateTransitionAnimation {
}; };
} }
}; };
startAnimationToWorkspaceFromOverlay(toWorkspaceState, widgetsView, startAnimationToWorkspaceFromOverlay(toWorkspaceState, toWorkspacePage, widgetsView,
widgetsView.getContentView(), widgetsView.getRevealView(), animated, widgetsView.getContentView(), widgetsView.getRevealView(), animated,
onCompleteRunnable, cb); onCompleteRunnable, cb);
} }
@@ -523,8 +524,8 @@ public class LauncherStateTransitionAnimation {
* Creates and starts a new animation to the workspace. * Creates and starts a new animation to the workspace.
*/ */
private void startAnimationToWorkspaceFromOverlay(final Workspace.State toWorkspaceState, private void startAnimationToWorkspaceFromOverlay(final Workspace.State toWorkspaceState,
final View fromView, final View contentView, final View revealView, final int toWorkspacePage, final View fromView, final View contentView,
final boolean animated, final Runnable onCompleteRunnable, final View revealView, final boolean animated, final Runnable onCompleteRunnable,
final PrivateTransitionCallbacks pCb) { final PrivateTransitionCallbacks pCb) {
final Resources res = mLauncher.getResources(); final Resources res = mLauncher.getResources();
final boolean material = Utilities.isLmpOrAbove(); final boolean material = Utilities.isLmpOrAbove();
@@ -545,8 +546,8 @@ public class LauncherStateTransitionAnimation {
// Create the workspace animation. // Create the workspace animation.
// NOTE: this call apparently also sets the state for the workspace if !animated // NOTE: this call apparently also sets the state for the workspace if !animated
Animator workspaceAnim = mLauncher.getWorkspace().getChangeStateAnimation( Animator workspaceAnim = mLauncher.getWorkspace().setStateWithAnimation(
toWorkspaceState, animated, layerViews); toWorkspaceState, toWorkspacePage, animated, layerViews);
if (animated && initialized) { if (animated && initialized) {
mStateAnimation = LauncherAnimUtils.createAnimatorSet(); mStateAnimation = LauncherAnimUtils.createAnimatorSet();
+2 -2
View File
@@ -1696,11 +1696,11 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
return OVERSCROLL_DAMP_FACTOR * f; return OVERSCROLL_DAMP_FACTOR * f;
} }
protected void enableFreeScroll() { public void enableFreeScroll() {
setEnableFreeScroll(true); setEnableFreeScroll(true);
} }
protected void disableFreeScroll() { public void disableFreeScroll() {
setEnableFreeScroll(false); setEnableFreeScroll(false);
} }
@@ -33,18 +33,16 @@ import android.widget.FrameLayout;
*/ */
public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener { public class SearchDropTargetBar extends FrameLayout implements DragController.DragListener {
private static final int sTransitionInDuration = 200; private static final int TRANSITION_DURATION = 200;
private static final int sTransitionOutDuration = 175;
private ObjectAnimator mDropTargetBarAnim; private ObjectAnimator mShowDropTargetBarAnim;
private ValueAnimator mQSBSearchBarAnim; private ValueAnimator mHideSearchBarAnim;
private static final AccelerateInterpolator sAccelerateInterpolator = private static final AccelerateInterpolator sAccelerateInterpolator =
new AccelerateInterpolator(); new AccelerateInterpolator();
private boolean mIsSearchBarHidden; private boolean mIsSearchBarHidden;
private View mQSBSearchBar; private View mQSBSearchBar;
private View mDropTargetBar; private View mDropTargetBar;
private int mBarHeight;
private boolean mDeferOnDragEnd = false; private boolean mDeferOnDragEnd = false;
// Drop targets // Drop targets
@@ -52,8 +50,6 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
private ButtonDropTarget mDeleteDropTarget; private ButtonDropTarget mDeleteDropTarget;
private ButtonDropTarget mUninstallDropTarget; private ButtonDropTarget mUninstallDropTarget;
private boolean mEnableDropDownDropTargets;
public SearchDropTargetBar(Context context, AttributeSet attrs) { public SearchDropTargetBar(Context context, AttributeSet attrs) {
this(context, attrs, 0); this(context, attrs, 0);
} }
@@ -82,17 +78,12 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
public void setQsbSearchBar(View qsb) { public void setQsbSearchBar(View qsb) {
mQSBSearchBar = qsb; mQSBSearchBar = qsb;
if (mQSBSearchBar != null) { if (mQSBSearchBar != null) {
if (mEnableDropDownDropTargets) { mHideSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "translationY", 0, setupAnimation(mHideSearchBarAnim, mQSBSearchBar);
-mBarHeight);
} else {
mQSBSearchBarAnim = LauncherAnimUtils.ofFloat(mQSBSearchBar, "alpha", 1f, 0f);
}
setupAnimation(mQSBSearchBarAnim, mQSBSearchBar);
} else { } else {
// Create a no-op animation of the search bar is null // Create a no-op animation of the search bar is null
mQSBSearchBarAnim = ValueAnimator.ofFloat(0, 0); mHideSearchBarAnim = ValueAnimator.ofFloat(0, 0);
mQSBSearchBarAnim.setDuration(sTransitionInDuration); mHideSearchBarAnim.setDuration(TRANSITION_DURATION);
} }
} }
@@ -106,7 +97,7 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
private void setupAnimation(ValueAnimator anim, final View v) { private void setupAnimation(ValueAnimator anim, final View v) {
anim.setInterpolator(sAccelerateInterpolator); anim.setInterpolator(sAccelerateInterpolator);
anim.setDuration(sTransitionInDuration); anim.setDuration(TRANSITION_DURATION);
anim.addListener(new AnimatorListenerAdapter() { anim.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
@@ -131,76 +122,74 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
mDeleteDropTarget.setSearchDropTargetBar(this); mDeleteDropTarget.setSearchDropTargetBar(this);
mUninstallDropTarget.setSearchDropTargetBar(this); mUninstallDropTarget.setSearchDropTargetBar(this);
mEnableDropDownDropTargets =
getResources().getBoolean(R.bool.config_useDropTargetDownTransition);
// Create the various fade animations // Create the various fade animations
if (mEnableDropDownDropTargets) { mDropTargetBar.setAlpha(0f);
LauncherAppState app = LauncherAppState.getInstance(); mShowDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "alpha", 0f, 1f);
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); setupAnimation(mShowDropTargetBarAnim, mDropTargetBar);
mBarHeight = grid.searchBarSpaceHeightPx;
mDropTargetBar.setTranslationY(-mBarHeight);
mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "translationY",
-mBarHeight, 0f);
} else {
mDropTargetBar.setAlpha(0f);
mDropTargetBarAnim = LauncherAnimUtils.ofFloat(mDropTargetBar, "alpha", 0f, 1f);
}
setupAnimation(mDropTargetBarAnim, mDropTargetBar);
} }
/**
* Finishes all the animations on the search and drop target bars.
*/
public void finishAnimations() { public void finishAnimations() {
prepareStartAnimation(mDropTargetBar); prepareStartAnimation(mDropTargetBar);
mDropTargetBarAnim.reverse(); mShowDropTargetBarAnim.reverse();
prepareStartAnimation(mQSBSearchBar); prepareStartAnimation(mQSBSearchBar);
mQSBSearchBarAnim.reverse(); mHideSearchBarAnim.reverse();
} }
/* /**
* Shows and hides the search bar. * Shows the search bar.
*/ */
public void showSearchBar(boolean animated) { public void showSearchBar(boolean animated) {
boolean needToCancelOngoingAnimation = mQSBSearchBarAnim.isRunning() && !animated; if (!mIsSearchBarHidden) return;
if (!mIsSearchBarHidden && !needToCancelOngoingAnimation) return;
if (animated) { if (animated) {
prepareStartAnimation(mQSBSearchBar); prepareStartAnimation(mQSBSearchBar);
mQSBSearchBarAnim.reverse(); mHideSearchBarAnim.reverse();
} else { } else {
mQSBSearchBarAnim.cancel(); mHideSearchBarAnim.cancel();
if (mQSBSearchBar != null && mEnableDropDownDropTargets) { if (mQSBSearchBar != null) {
mQSBSearchBar.setTranslationY(0);
} else if (mQSBSearchBar != null) {
mQSBSearchBar.setAlpha(1f); mQSBSearchBar.setAlpha(1f);
} }
} }
mIsSearchBarHidden = false; mIsSearchBarHidden = false;
} }
/**
* Hides the search bar. We only use this for clings.
*/
public void hideSearchBar(boolean animated) { public void hideSearchBar(boolean animated) {
boolean needToCancelOngoingAnimation = mQSBSearchBarAnim.isRunning() && !animated; if (mIsSearchBarHidden) return;
if (mIsSearchBarHidden && !needToCancelOngoingAnimation) return;
if (animated) { if (animated) {
prepareStartAnimation(mQSBSearchBar); prepareStartAnimation(mQSBSearchBar);
mQSBSearchBarAnim.start(); mHideSearchBarAnim.start();
} else { } else {
mQSBSearchBarAnim.cancel(); mHideSearchBarAnim.cancel();
if (mQSBSearchBar != null && mEnableDropDownDropTargets) { if (mQSBSearchBar != null) {
mQSBSearchBar.setTranslationY(-mBarHeight);
} else if (mQSBSearchBar != null) {
mQSBSearchBar.setAlpha(0f); mQSBSearchBar.setAlpha(0f);
} }
} }
mIsSearchBarHidden = true; mIsSearchBarHidden = true;
} }
/* /**
* Gets various transition durations. * Shows the drop target bar.
*/ */
public int getTransitionInDuration() { public void showDeleteTarget() {
return sTransitionInDuration; // Animate out the QSB search bar, and animate in the drop target bar
prepareStartAnimation(mDropTargetBar);
mShowDropTargetBarAnim.start();
hideSearchBar(true);
} }
public int getTransitionOutDuration() {
return sTransitionOutDuration; /**
* Hides the drop target bar.
*/
public void hideDeleteTarget() {
// Restore the QSB search bar, and animate out the drop target bar
prepareStartAnimation(mDropTargetBar);
mShowDropTargetBarAnim.reverse();
showSearchBar(true);
} }
/* /*
@@ -211,26 +200,6 @@ public class SearchDropTargetBar extends FrameLayout implements DragController.D
showDeleteTarget(); showDeleteTarget();
} }
public void showDeleteTarget() {
// Animate out the QSB search bar, and animate in the drop target bar
prepareStartAnimation(mDropTargetBar);
mDropTargetBarAnim.start();
if (!mIsSearchBarHidden) {
prepareStartAnimation(mQSBSearchBar);
mQSBSearchBarAnim.start();
}
}
public void hideDeleteTarget() {
// Restore the QSB search bar, and animate out the drop target bar
prepareStartAnimation(mDropTargetBar);
mDropTargetBarAnim.reverse();
if (!mIsSearchBarHidden) {
prepareStartAnimation(mQSBSearchBar);
mQSBSearchBarAnim.reverse();
}
}
public void deferOnDragEnd() { public void deferOnDragEnd() {
mDeferOnDragEnd = true; mDeferOnDragEnd = true;
} }
+34 -498
View File
@@ -17,15 +17,10 @@
package com.android.launcher3; package com.android.launcher3;
import android.animation.Animator; import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.LayoutTransition; import android.animation.LayoutTransition;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder; import android.animation.PropertyValuesHolder;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.WallpaperManager; import android.app.WallpaperManager;
import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetHostView;
@@ -99,12 +94,9 @@ public class Workspace extends SmoothPagedView
protected static final int SNAP_OFF_EMPTY_SCREEN_DURATION = 400; protected static final int SNAP_OFF_EMPTY_SCREEN_DURATION = 400;
protected static final int FADE_EMPTY_SCREEN_DURATION = 150; protected static final int FADE_EMPTY_SCREEN_DURATION = 150;
private static final int BACKGROUND_FADE_OUT_DURATION = 350;
private static final int ADJACENT_SCREEN_DROP_DURATION = 300; private static final int ADJACENT_SCREEN_DROP_DURATION = 300;
private static final int FLING_THRESHOLD_VELOCITY = 500; private static final int FLING_THRESHOLD_VELOCITY = 500;
private static final float ALPHA_CUTOFF_THRESHOLD = 0.01f;
static final boolean MAP_NO_RECURSE = false; static final boolean MAP_NO_RECURSE = false;
static final boolean MAP_RECURSE = true; static final boolean MAP_RECURSE = true;
@@ -113,10 +105,6 @@ public class Workspace extends SmoothPagedView
private ObjectAnimator mChildrenOutlineFadeOutAnimation; private ObjectAnimator mChildrenOutlineFadeOutAnimation;
private float mChildrenOutlineAlpha = 0; private float mChildrenOutlineAlpha = 0;
// These properties refer to the background protection gradient used for AllApps and Customize
private ValueAnimator mBackgroundFadeInAnimation;
private ValueAnimator mBackgroundFadeOutAnimation;
private static final long CUSTOM_CONTENT_GESTURE_DELAY = 200; private static final long CUSTOM_CONTENT_GESTURE_DELAY = 200;
private long mTouchDownTime = -1; private long mTouchDownTime = -1;
private long mCustomContentShowTime = -1; private long mCustomContentShowTime = -1;
@@ -129,7 +117,6 @@ public class Workspace extends SmoothPagedView
private int mDefaultPage; private int mDefaultPage;
private ShortcutAndWidgetContainer mDragSourceInternal; private ShortcutAndWidgetContainer mDragSourceInternal;
@Thunk static boolean sAccessibilityEnabled;
// The screen id used for the empty screen always present to the right. // The screen id used for the empty screen always present to the right.
final static long EXTRA_EMPTY_SCREEN_ID = -201; final static long EXTRA_EMPTY_SCREEN_ID = -201;
@@ -272,14 +259,7 @@ public class Workspace extends SmoothPagedView
private float mSavedTranslationX; private float mSavedTranslationX;
private float mCurrentScale; private float mCurrentScale;
private float mNewScale;
@Thunk float[] mOldBackgroundAlphas;
private float[] mOldAlphas;
@Thunk float[] mNewBackgroundAlphas;
private float[] mNewAlphas;
private int mLastChildCount = -1;
private float mTransitionProgress; private float mTransitionProgress;
@Thunk Animator mStateAnimator = null;
float mOverScrollEffect = 0f; float mOverScrollEffect = 0f;
@@ -294,6 +274,9 @@ public class Workspace extends SmoothPagedView
boolean mShouldSendPageSettled; boolean mShouldSendPageSettled;
int mLastOverlaySroll = 0; int mLastOverlaySroll = 0;
// Handles workspace state transitions
private WorkspaceStateTransitionAnimation mStateTransitionAnimation;
private final Runnable mBindPages = new Runnable() { private final Runnable mBindPages = new Runnable() {
@Override @Override
public void run() { public void run() {
@@ -329,6 +312,7 @@ public class Workspace extends SmoothPagedView
setDataIsReady(); setDataIsReady();
mLauncher = (Launcher) context; mLauncher = (Launcher) context;
mStateTransitionAnimation = new WorkspaceStateTransitionAnimation(mLauncher, this);
final Resources res = getResources(); final Resources res = getResources();
mWorkspaceFadeInAdjacentScreens = LauncherAppState.getInstance().getDynamicGrid(). mWorkspaceFadeInAdjacentScreens = LauncherAppState.getInstance().getDynamicGrid().
getDeviceProfile().shouldFadeAdjacentWorkspaceScreens(); getDeviceProfile().shouldFadeAdjacentWorkspaceScreens();
@@ -1583,37 +1567,6 @@ public class Workspace extends SmoothPagedView
return mChildrenOutlineAlpha; return mChildrenOutlineAlpha;
} }
private void animateBackgroundGradient(float finalAlpha, boolean animated) {
final DragLayer dragLayer = mLauncher.getDragLayer();
if (mBackgroundFadeInAnimation != null) {
mBackgroundFadeInAnimation.cancel();
mBackgroundFadeInAnimation = null;
}
if (mBackgroundFadeOutAnimation != null) {
mBackgroundFadeOutAnimation.cancel();
mBackgroundFadeOutAnimation = null;
}
float startAlpha = dragLayer.getBackgroundAlpha();
if (finalAlpha != startAlpha) {
if (animated) {
mBackgroundFadeOutAnimation =
LauncherAnimUtils.ofFloat(this, startAlpha, finalAlpha);
mBackgroundFadeOutAnimation.addUpdateListener(new AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
dragLayer.setBackgroundAlpha(
((Float)animation.getAnimatedValue()).floatValue());
}
});
mBackgroundFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
mBackgroundFadeOutAnimation.start();
} else {
dragLayer.setBackgroundAlpha(finalAlpha);
}
}
}
float backgroundAlphaInterpolator(float r) { float backgroundAlphaInterpolator(float r) {
float pivotA = 0.1f; float pivotA = 0.1f;
float pivotB = 0.4f; float pivotB = 0.4f;
@@ -1737,7 +1690,7 @@ public class Workspace extends SmoothPagedView
OnClickListener listener = new OnClickListener() { OnClickListener listener = new OnClickListener() {
@Override @Override
public void onClick(View arg0) { public void onClick(View arg0) {
enterOverviewMode(); mLauncher.showOverviewMode(true);
} }
}; };
return listener; return listener;
@@ -1797,9 +1750,6 @@ public class Workspace extends SmoothPagedView
getPageIndicator().setOnClickListener(listener); getPageIndicator().setOnClickListener(listener);
} }
} }
AccessibilityManager am = (AccessibilityManager)
getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
sAccessibilityEnabled = am.isEnabled();
// Update wallpaper dimensions if they were changed since last onResume // Update wallpaper dimensions if they were changed since last onResume
// (we also always set the wallpaper dimensions in the constructor) // (we also always set the wallpaper dimensions in the constructor)
@@ -1969,64 +1919,6 @@ public class Workspace extends SmoothPagedView
position[0], position[1], 0, null); position[0], position[1], 0, null);
} }
/*
* This interpolator emulates the rate at which the perceived scale of an object changes
* as its distance from a camera increases. When this interpolator is applied to a scale
* animation on a view, it evokes the sense that the object is shrinking due to moving away
* from the camera.
*/
static class ZInterpolator implements TimeInterpolator {
private float focalLength;
public ZInterpolator(float foc) {
focalLength = foc;
}
public float getInterpolation(float input) {
return (1.0f - focalLength / (focalLength + input)) /
(1.0f - focalLength / (focalLength + 1.0f));
}
}
/*
* The exact reverse of ZInterpolator.
*/
static class InverseZInterpolator implements TimeInterpolator {
private ZInterpolator zInterpolator;
public InverseZInterpolator(float foc) {
zInterpolator = new ZInterpolator(foc);
}
public float getInterpolation(float input) {
return 1 - zInterpolator.getInterpolation(1 - input);
}
}
/*
* ZInterpolator compounded with an ease-out.
*/
static class ZoomOutInterpolator implements TimeInterpolator {
private final DecelerateInterpolator decelerate = new DecelerateInterpolator(0.75f);
private final ZInterpolator zInterpolator = new ZInterpolator(0.13f);
public float getInterpolation(float input) {
return decelerate.getInterpolation(zInterpolator.getInterpolation(input));
}
}
/*
* InvereZInterpolator compounded with an ease-out.
*/
static class ZoomInInterpolator implements TimeInterpolator {
private final InverseZInterpolator inverseZInterpolator = new InverseZInterpolator(0.35f);
private final DecelerateInterpolator decelerate = new DecelerateInterpolator(3.0f);
public float getInterpolation(float input) {
return decelerate.getInterpolation(inverseZInterpolator.getInterpolation(input));
}
}
private final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
/* /*
* *
* We call these methods (onDragStartedWithItemSpans/onDragStartedWithSize) whenever we * We call these methods (onDragStartedWithItemSpans/onDragStartedWithSize) whenever we
@@ -2090,21 +1982,6 @@ public class Workspace extends SmoothPagedView
dragLayer.clearAllResizeFrames(); dragLayer.clearAllResizeFrames();
} }
private void initAnimationArrays() {
final int childCount = getChildCount();
if (mLastChildCount == childCount) return;
mOldBackgroundAlphas = new float[childCount];
mOldAlphas = new float[childCount];
mNewBackgroundAlphas = new float[childCount];
mNewAlphas = new float[childCount];
}
Animator getChangeStateAnimation(final State state, boolean animated,
HashMap<View, Integer> layerViews) {
return getChangeStateAnimation(state, animated, 0, -1, layerViews);
}
@Override @Override
protected void getFreeScrollPageRange(int[] range) { protected void getFreeScrollPageRange(int[] range) {
getOverviewModePages(range); getOverviewModePages(range);
@@ -2151,41 +2028,6 @@ public class Workspace extends SmoothPagedView
return mState == State.OVERVIEW; return mState == State.OVERVIEW;
} }
public boolean enterOverviewMode() {
if (mTouchState != TOUCH_STATE_REST) {
return false;
}
enableOverviewMode(true, -1, true);
return true;
}
public void exitOverviewMode(boolean animated) {
exitOverviewMode(-1, animated);
}
public void exitOverviewMode(int snapPage, boolean animated) {
enableOverviewMode(false, snapPage, animated);
}
private void enableOverviewMode(boolean enable, int snapPage, boolean animated) {
State finalState = Workspace.State.OVERVIEW;
if (!enable) {
finalState = Workspace.State.NORMAL;
}
Animator workspaceAnim = getChangeStateAnimation(finalState, animated, 0, snapPage);
if (workspaceAnim != null) {
onTransitionPrepare();
workspaceAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator arg0) {
onTransitionEnd();
}
});
workspaceAnim.start();
}
}
int getOverviewModeTranslationY() { int getOverviewModeTranslationY() {
LauncherAppState app = LauncherAppState.getInstance(); LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile(); DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
@@ -2208,10 +2050,22 @@ public class Workspace extends SmoothPagedView
} }
} }
private void setState(State state) { /**
mState = state; * Sets the current workspace {@link State}, returning an animation transitioning the workspace
* to that new state.
*/
public Animator setStateWithAnimation(State toState, int toPage, boolean animated,
HashMap<View, Integer> layerViews) {
// Create the animation to the new state
Animator workspaceAnim = mStateTransitionAnimation.getAnimationToState(getState(),
toState, toPage, animated, layerViews);
// Update the current state
mState = toState;
updateInteractionForState(); updateInteractionForState();
updateAccessibilityFlags(); updateAccessibilityFlags();
return workspaceAnim;
} }
State getState() { State getState() {
@@ -2225,321 +2079,15 @@ public class Workspace extends SmoothPagedView
setImportantForAccessibility(accessible); setImportantForAccessibility(accessible);
} }
private static final int HIDE_WORKSPACE_DURATION = 100;
Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage) {
return getChangeStateAnimation(state, animated, delay, snapPage, null);
}
Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage,
HashMap<View, Integer> layerViews) {
if (mState == state) {
return null;
}
// Initialize animation arrays for the first time if necessary
initAnimationArrays();
AnimatorSet anim = animated ? LauncherAnimUtils.createAnimatorSet() : null;
// We only want a single instance of a workspace animation to be running at once, so
// we cancel any incomplete transition.
if (mStateAnimator != null) {
mStateAnimator.cancel();
}
mStateAnimator = anim;
final State oldState = mState;
final boolean oldStateIsNormal = (oldState == State.NORMAL);
final boolean oldStateIsSpringLoaded = (oldState == State.SPRING_LOADED);
final boolean oldStateIsNormalHidden = (oldState == State.NORMAL_HIDDEN);
final boolean oldStateIsOverviewHidden = (oldState == State.OVERVIEW_HIDDEN);
final boolean oldStateIsOverview = (oldState == State.OVERVIEW);
setState(state);
final boolean stateIsNormal = (state == State.NORMAL);
final boolean stateIsSpringLoaded = (state == State.SPRING_LOADED);
final boolean stateIsNormalHidden = (state == State.NORMAL_HIDDEN);
final boolean stateIsOverviewHidden = (state == State.OVERVIEW_HIDDEN);
final boolean stateIsOverview = (state == State.OVERVIEW);
float finalBackgroundAlpha = (stateIsSpringLoaded || stateIsOverview) ? 1.0f : 0f;
float finalHotseatAndPageIndicatorAlpha = (stateIsNormal || stateIsSpringLoaded) ? 1f : 0f;
float finalOverviewPanelAlpha = stateIsOverview ? 1f : 0f;
// We keep the search bar visible on the workspace and in AllApps now
boolean showSearchBar = stateIsNormal ||
(mLauncher.isAllAppsSearchOverridden() && stateIsNormalHidden);
float finalSearchBarAlpha = showSearchBar ? 1f : 0f;
float finalWorkspaceTranslationY = stateIsOverview || stateIsOverviewHidden ?
getOverviewModeTranslationY() : 0;
boolean workspaceToAllApps = (oldStateIsNormal && stateIsNormalHidden);
boolean overviewToAllApps = (oldStateIsOverview && stateIsOverviewHidden);
boolean allAppsToWorkspace = (stateIsNormalHidden && stateIsNormal);
boolean workspaceToOverview = (oldStateIsNormal && stateIsOverview);
boolean overviewToWorkspace = (oldStateIsOverview && stateIsNormal);
mNewScale = 1.0f;
if (oldStateIsOverview) {
disableFreeScroll();
} else if (stateIsOverview) {
enableFreeScroll();
}
if (state != State.NORMAL) {
if (stateIsSpringLoaded) {
mNewScale = mSpringLoadedShrinkFactor;
} else if (stateIsOverview || stateIsOverviewHidden) {
mNewScale = mOverviewModeShrinkFactor;
}
}
final int duration;
if (workspaceToAllApps || overviewToAllApps) {
duration = HIDE_WORKSPACE_DURATION; //getResources().getInteger(R.integer.config_workspaceUnshrinkTime);
} else if (workspaceToOverview || overviewToWorkspace) {
duration = getResources().getInteger(R.integer.config_overviewTransitionTime);
} else {
duration = getResources().getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
}
if (snapPage == -1) {
snapPage = getPageNearestToCenterOfScreen();
}
snapToPage(snapPage, duration, mZoomInInterpolator);
for (int i = 0; i < getChildCount(); i++) {
final CellLayout cl = (CellLayout) getChildAt(i);
boolean isCurrentPage = (i == snapPage);
float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
float finalAlpha;
if (stateIsNormalHidden || stateIsOverviewHidden) {
finalAlpha = 0f;
} else if (stateIsNormal && mWorkspaceFadeInAdjacentScreens) {
finalAlpha = (i == snapPage || i < numCustomPages()) ? 1f : 0f;
} else {
finalAlpha = 1f;
}
// If we are animating to/from the small state, then hide the side pages and fade the
// current page in
if (!mIsSwitchingState) {
if (workspaceToAllApps || allAppsToWorkspace) {
if (allAppsToWorkspace && isCurrentPage) {
initialAlpha = 0f;
} else if (!isCurrentPage) {
initialAlpha = finalAlpha = 0f;
}
cl.setShortcutAndWidgetAlpha(initialAlpha);
}
}
mOldAlphas[i] = initialAlpha;
mNewAlphas[i] = finalAlpha;
if (animated) {
mOldBackgroundAlphas[i] = cl.getBackgroundAlpha();
mNewBackgroundAlphas[i] = finalBackgroundAlpha;
} else {
cl.setBackgroundAlpha(finalBackgroundAlpha);
cl.setShortcutAndWidgetAlpha(finalAlpha);
}
}
final View searchBar = mLauncher.getOrCreateQsbBar();
final View overviewPanel = mLauncher.getOverviewPanel();
final View hotseat = mLauncher.getHotseat();
final View pageIndicator = getPageIndicator();
if (animated) {
LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(this);
scale.scaleX(mNewScale)
.scaleY(mNewScale)
.translationY(finalWorkspaceTranslationY)
.setDuration(duration)
.setInterpolator(mZoomInInterpolator);
anim.play(scale);
for (int index = 0; index < getChildCount(); index++) {
final int i = index;
final CellLayout cl = (CellLayout) getChildAt(i);
float currentAlpha = cl.getShortcutsAndWidgets().getAlpha();
if (mOldAlphas[i] == 0 && mNewAlphas[i] == 0) {
cl.setBackgroundAlpha(mNewBackgroundAlphas[i]);
cl.setShortcutAndWidgetAlpha(mNewAlphas[i]);
} else {
if (layerViews != null) {
layerViews.put(cl, LauncherStateTransitionAnimation.BUILD_LAYER);
}
if (mOldAlphas[i] != mNewAlphas[i] || currentAlpha != mNewAlphas[i]) {
LauncherViewPropertyAnimator alphaAnim =
new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
alphaAnim.alpha(mNewAlphas[i])
.setDuration(duration)
.setInterpolator(mZoomInInterpolator);
anim.play(alphaAnim);
}
if (mOldBackgroundAlphas[i] != 0 ||
mNewBackgroundAlphas[i] != 0) {
ValueAnimator bgAnim =
LauncherAnimUtils.ofFloat(cl, 0f, 1f);
bgAnim.setInterpolator(mZoomInInterpolator);
bgAnim.setDuration(duration);
bgAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
public void onAnimationUpdate(float a, float b) {
cl.setBackgroundAlpha(
a * mOldBackgroundAlphas[i] +
b * mNewBackgroundAlphas[i]);
}
});
anim.play(bgAnim);
}
}
}
Animator pageIndicatorAlpha = null;
if (pageIndicator != null) {
pageIndicatorAlpha = new LauncherViewPropertyAnimator(pageIndicator)
.alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
pageIndicatorAlpha.addListener(new AlphaUpdateListener(pageIndicator));
} else {
// create a dummy animation so we don't need to do null checks later
pageIndicatorAlpha = ValueAnimator.ofFloat(0, 0);
}
LauncherViewPropertyAnimator hotseatAlpha = new LauncherViewPropertyAnimator(hotseat)
.alpha(finalHotseatAndPageIndicatorAlpha);
hotseatAlpha.addListener(new AlphaUpdateListener(hotseat));
LauncherViewPropertyAnimator overviewPanelAlpha =
new LauncherViewPropertyAnimator(overviewPanel).alpha(finalOverviewPanelAlpha);
overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
// For animation optimations, we may need to provide the Launcher transition
// with a set of views on which to force build layers in certain scenarios.
hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
if (layerViews != null) {
// If layerViews is not null, we add these views, and indicate that
// the caller can manage layer state.
layerViews.put(hotseat, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER);
layerViews.put(overviewPanel, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER);
} else {
// Otherwise let the animator handle layer management.
hotseatAlpha.withLayer();
overviewPanelAlpha.withLayer();
}
if (workspaceToOverview) {
pageIndicatorAlpha.setInterpolator(new DecelerateInterpolator(2));
hotseatAlpha.setInterpolator(new DecelerateInterpolator(2));
overviewPanelAlpha.setInterpolator(null);
} else if (overviewToWorkspace) {
pageIndicatorAlpha.setInterpolator(null);
hotseatAlpha.setInterpolator(null);
overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2));
}
overviewPanelAlpha.setDuration(duration);
pageIndicatorAlpha.setDuration(duration);
hotseatAlpha.setDuration(duration);
if (searchBar != null) {
LauncherViewPropertyAnimator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
.alpha(finalSearchBarAlpha);
searchBarAlpha.addListener(new AlphaUpdateListener(searchBar));
searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
if (layerViews != null) {
// If layerViews is not null, we add these views, and indicate that
// the caller can manage layer state.
layerViews.put(searchBar, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER);
} else {
// Otherwise let the animator handle layer management.
searchBarAlpha.withLayer();
}
searchBarAlpha.setDuration(duration);
anim.play(searchBarAlpha);
}
anim.play(overviewPanelAlpha);
anim.play(hotseatAlpha);
anim.play(pageIndicatorAlpha);
anim.setStartDelay(delay);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mStateAnimator = null;
}
});
} else {
overviewPanel.setAlpha(finalOverviewPanelAlpha);
AlphaUpdateListener.updateVisibility(overviewPanel);
hotseat.setAlpha(finalHotseatAndPageIndicatorAlpha);
AlphaUpdateListener.updateVisibility(hotseat);
if (pageIndicator != null) {
pageIndicator.setAlpha(finalHotseatAndPageIndicatorAlpha);
AlphaUpdateListener.updateVisibility(pageIndicator);
}
if (searchBar != null) {
searchBar.setAlpha(finalSearchBarAlpha);
AlphaUpdateListener.updateVisibility(searchBar);
}
updateCustomContentVisibility();
setScaleX(mNewScale);
setScaleY(mNewScale);
setTranslationY(finalWorkspaceTranslationY);
}
if (stateIsNormal) {
animateBackgroundGradient(0f, animated);
} else {
animateBackgroundGradient(getResources().getInteger(
R.integer.config_workspaceScrimAlpha) / 100f, animated);
}
return anim;
}
static class AlphaUpdateListener implements AnimatorUpdateListener, AnimatorListener {
View view;
public AlphaUpdateListener(View v) {
view = v;
}
@Override
public void onAnimationUpdate(ValueAnimator arg0) {
updateVisibility(view);
}
public static void updateVisibility(View view) {
// We want to avoid the extra layout pass by setting the views to GONE unless
// accessibility is on, in which case not setting them to GONE causes a glitch.
int invisibleState = sAccessibilityEnabled ? GONE : INVISIBLE;
if (view.getAlpha() < ALPHA_CUTOFF_THRESHOLD && view.getVisibility() != invisibleState) {
view.setVisibility(invisibleState);
} else if (view.getAlpha() > ALPHA_CUTOFF_THRESHOLD
&& view.getVisibility() != VISIBLE) {
view.setVisibility(VISIBLE);
}
}
@Override
public void onAnimationCancel(Animator arg0) {
}
@Override
public void onAnimationEnd(Animator arg0) {
updateVisibility(view);
}
@Override
public void onAnimationRepeat(Animator arg0) {
}
@Override
public void onAnimationStart(Animator arg0) {
// We want the views to be visible for animation, so fade-in/out is visible
view.setVisibility(VISIBLE);
}
}
@Override @Override
public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) { public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
onTransitionPrepare(); mIsSwitchingState = true;
// Invalidate here to ensure that the pages are rendered during the state change transition.
invalidate();
updateChildrenLayersEnabled(false);
hideCustomContentIfNecessary();
} }
@Override @Override
@@ -2553,17 +2101,9 @@ public class Workspace extends SmoothPagedView
@Override @Override
public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) { public void onLauncherTransitionEnd(Launcher l, boolean animated, boolean toWorkspace) {
onTransitionEnd(); mIsSwitchingState = false;
}
private void onTransitionPrepare() {
mIsSwitchingState = true;
// Invalidate here to ensure that the pages are rendered during the state change transition.
invalidate();
updateChildrenLayersEnabled(false); updateChildrenLayersEnabled(false);
hideCustomContentIfNecessary(); showCustomContentIfNecessary();
} }
void updateCustomContentVisibility() { void updateCustomContentVisibility() {
@@ -2589,12 +2129,6 @@ public class Workspace extends SmoothPagedView
} }
} }
@Thunk void onTransitionEnd() {
mIsSwitchingState = false;
updateChildrenLayersEnabled(false);
showCustomContentIfNecessary();
}
@Override @Override
public View getContent() { public View getContent() {
return this; return this;
@@ -3106,7 +2640,7 @@ public class Workspace extends SmoothPagedView
} }
} }
int snapScreen = -1; int snapScreen = WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE;
boolean resizeOnDrop = false; boolean resizeOnDrop = false;
if (d.dragSource != this) { if (d.dragSource != this) {
final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0], final int[] touchXY = new int[] { (int) mDragViewVisualCenter[0],
@@ -3267,7 +2801,9 @@ public class Workspace extends SmoothPagedView
animateWidgetDrop(info, parent, d.dragView, animateWidgetDrop(info, parent, d.dragView,
onCompleteRunnable, animationType, cell, false); onCompleteRunnable, animationType, cell, false);
} else { } else {
int duration = snapScreen < 0 ? -1 : ADJACENT_SCREEN_DROP_DURATION; int duration = snapScreen < 0 ?
WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE :
ADJACENT_SCREEN_DROP_DURATION;
mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration, mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell, duration,
onCompleteRunnable, this); onCompleteRunnable, this);
} }
@@ -4165,8 +3701,8 @@ public class Workspace extends SmoothPagedView
public void setFinalTransitionTransform(CellLayout layout) { public void setFinalTransitionTransform(CellLayout layout) {
if (isSwitchingState()) { if (isSwitchingState()) {
mCurrentScale = getScaleX(); mCurrentScale = getScaleX();
setScaleX(mNewScale); setScaleX(mStateTransitionAnimation.getFinalScale());
setScaleY(mNewScale); setScaleY(mStateTransitionAnimation.getFinalScale());
} }
} }
public void resetTransitionTransform(CellLayout layout) { public void resetTransitionTransform(CellLayout layout) {
@@ -0,0 +1,519 @@
/*
* Copyright (C) 2015 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.launcher3;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.view.View;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.DecelerateInterpolator;
import com.android.launcher3.util.Thunk;
import java.util.HashMap;
/**
* A convenience class to update a view's visibility state after an alpha animation.
*/
class AlphaUpdateListener extends AnimatorListenerAdapter implements ValueAnimator.AnimatorUpdateListener {
private static final float ALPHA_CUTOFF_THRESHOLD = 0.01f;
private View mView;
private boolean mAccessibilityEnabled;
public AlphaUpdateListener(View v, boolean accessibilityEnabled) {
mView = v;
mAccessibilityEnabled = accessibilityEnabled;
}
@Override
public void onAnimationUpdate(ValueAnimator arg0) {
updateVisibility(mView, mAccessibilityEnabled);
}
public static void updateVisibility(View view, boolean accessibilityEnabled) {
// We want to avoid the extra layout pass by setting the views to GONE unless
// accessibility is on, in which case not setting them to GONE causes a glitch.
int invisibleState = accessibilityEnabled ? View.GONE : View.INVISIBLE;
if (view.getAlpha() < ALPHA_CUTOFF_THRESHOLD && view.getVisibility() != invisibleState) {
view.setVisibility(invisibleState);
} else if (view.getAlpha() > ALPHA_CUTOFF_THRESHOLD
&& view.getVisibility() != View.VISIBLE) {
view.setVisibility(View.VISIBLE);
}
}
@Override
public void onAnimationEnd(Animator arg0) {
updateVisibility(mView, mAccessibilityEnabled);
}
@Override
public void onAnimationStart(Animator arg0) {
// We want the views to be visible for animation, so fade-in/out is visible
mView.setVisibility(View.VISIBLE);
}
}
/**
* This interpolator emulates the rate at which the perceived scale of an object changes
* as its distance from a camera increases. When this interpolator is applied to a scale
* animation on a view, it evokes the sense that the object is shrinking due to moving away
* from the camera.
*/
class ZInterpolator implements TimeInterpolator {
private float focalLength;
public ZInterpolator(float foc) {
focalLength = foc;
}
public float getInterpolation(float input) {
return (1.0f - focalLength / (focalLength + input)) /
(1.0f - focalLength / (focalLength + 1.0f));
}
}
/**
* The exact reverse of ZInterpolator.
*/
class InverseZInterpolator implements TimeInterpolator {
private ZInterpolator zInterpolator;
public InverseZInterpolator(float foc) {
zInterpolator = new ZInterpolator(foc);
}
public float getInterpolation(float input) {
return 1 - zInterpolator.getInterpolation(1 - input);
}
}
/**
* InverseZInterpolator compounded with an ease-out.
*/
class ZoomInInterpolator implements TimeInterpolator {
private final InverseZInterpolator inverseZInterpolator = new InverseZInterpolator(0.35f);
private final DecelerateInterpolator decelerate = new DecelerateInterpolator(3.0f);
public float getInterpolation(float input) {
return decelerate.getInterpolation(inverseZInterpolator.getInterpolation(input));
}
}
/**
* Manages the animations between each of the workspace states.
*/
public class WorkspaceStateTransitionAnimation {
public static final String TAG = "WorkspaceStateTransitionAnimation";
public static final int SCROLL_TO_CURRENT_PAGE = -1;
@Thunk static final int BACKGROUND_FADE_OUT_DURATION = 350;
final @Thunk Launcher mLauncher;
final @Thunk Workspace mWorkspace;
@Thunk AnimatorSet mStateAnimator;
@Thunk float[] mOldBackgroundAlphas;
@Thunk float[] mOldAlphas;
@Thunk float[] mNewBackgroundAlphas;
@Thunk float[] mNewAlphas;
@Thunk int mLastChildCount = -1;
@Thunk float mCurrentScale;
@Thunk float mNewScale;
@Thunk final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
// These properties refer to the background protection gradient used for AllApps and Customize
@Thunk ValueAnimator mBackgroundFadeInAnimation;
@Thunk ValueAnimator mBackgroundFadeOutAnimation;
@Thunk float mSpringLoadedShrinkFactor;
@Thunk float mOverviewModeShrinkFactor;
@Thunk float mWorkspaceScrimAlpha;
@Thunk int mAllAppsTransitionTime;
@Thunk int mOverviewTransitionTime;
@Thunk int mOverlayTransitionTime;
@Thunk boolean mWorkspaceFadeInAdjacentScreens;
public WorkspaceStateTransitionAnimation(Launcher launcher, Workspace workspace) {
mLauncher = launcher;
mWorkspace = workspace;
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
Resources res = launcher.getResources();
mAllAppsTransitionTime = res.getInteger(R.integer.config_workspaceUnshrinkTime);
mOverviewTransitionTime = res.getInteger(R.integer.config_overviewTransitionTime);
mOverlayTransitionTime = res.getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
mSpringLoadedShrinkFactor =
res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100f;
mWorkspaceScrimAlpha = res.getInteger(R.integer.config_workspaceScrimAlpha) / 100f;
mOverviewModeShrinkFactor = grid.getOverviewModeScale();
mWorkspaceFadeInAdjacentScreens = grid.shouldFadeAdjacentWorkspaceScreens();
}
public AnimatorSet getAnimationToState(Workspace.State fromState, Workspace.State toState,
int toPage, boolean animated,
HashMap<View, Integer> layerViews) {
getAnimation(fromState, toState, toPage, animated, layerViews);
return mStateAnimator;
}
public float getFinalScale() {
return mNewScale;
}
/**
* Starts a transition animation for the workspace.
*/
private void getAnimation(final Workspace.State fromState, final Workspace.State toState,
int toPage, final boolean animated,
final HashMap<View, Integer> layerViews) {
AccessibilityManager am = (AccessibilityManager)
mLauncher.getSystemService(Context.ACCESSIBILITY_SERVICE);
boolean accessibilityEnabled = am.isEnabled();
// Reinitialize animation arrays for the current workspace state
reinitializeAnimationArrays();
// Cancel existing workspace animations and create a new animator set if requested
cancelAnimation();
if (animated) {
mStateAnimator = LauncherAnimUtils.createAnimatorSet();
}
// Update the workspace state
final boolean oldStateIsNormal = (fromState == Workspace.State.NORMAL);
final boolean oldStateIsSpringLoaded = (fromState == Workspace.State.SPRING_LOADED);
final boolean oldStateIsNormalHidden = (fromState == Workspace.State.NORMAL_HIDDEN);
final boolean oldStateIsOverviewHidden = (fromState == Workspace.State.OVERVIEW_HIDDEN);
final boolean oldStateIsOverview = (fromState == Workspace.State.OVERVIEW);
final boolean stateIsNormal = (toState == Workspace.State.NORMAL);
final boolean stateIsSpringLoaded = (toState == Workspace.State.SPRING_LOADED);
final boolean stateIsNormalHidden = (toState == Workspace.State.NORMAL_HIDDEN);
final boolean stateIsOverviewHidden = (toState == Workspace.State.OVERVIEW_HIDDEN);
final boolean stateIsOverview = (toState == Workspace.State.OVERVIEW);
final boolean workspaceToAllApps = (oldStateIsNormal && stateIsNormalHidden);
final boolean overviewToAllApps = (oldStateIsOverview && stateIsOverviewHidden);
final boolean allAppsToWorkspace = (stateIsNormalHidden && stateIsNormal);
final boolean workspaceToOverview = (oldStateIsNormal && stateIsOverview);
final boolean overviewToWorkspace = (oldStateIsOverview && stateIsNormal);
float finalBackgroundAlpha = (stateIsSpringLoaded || stateIsOverview) ? 1.0f : 0f;
float finalHotseatAndPageIndicatorAlpha = (stateIsNormal || stateIsSpringLoaded) ? 1f : 0f;
float finalOverviewPanelAlpha = stateIsOverview ? 1f : 0f;
// We keep the search bar visible on the workspace and in AllApps now
boolean showSearchBar = stateIsNormal ||
(mLauncher.isAllAppsSearchOverridden() && stateIsNormalHidden);
float finalSearchBarAlpha = showSearchBar ? 1f : 0f;
float finalWorkspaceTranslationY = stateIsOverview || stateIsOverviewHidden ?
mWorkspace.getOverviewModeTranslationY() : 0;
final int childCount = mWorkspace.getChildCount();
final int customPageCount = mWorkspace.numCustomPages();
mNewScale = 1.0f;
if (oldStateIsOverview) {
mWorkspace.disableFreeScroll();
} else if (stateIsOverview) {
mWorkspace.enableFreeScroll();
}
if (!stateIsNormal) {
if (stateIsSpringLoaded) {
mNewScale = mSpringLoadedShrinkFactor;
} else if (stateIsOverview || stateIsOverviewHidden) {
mNewScale = mOverviewModeShrinkFactor;
}
}
final int duration;
if (workspaceToAllApps || overviewToAllApps) {
duration = mAllAppsTransitionTime;
} else if (workspaceToOverview || overviewToWorkspace) {
duration = mOverviewTransitionTime;
} else {
duration = mOverlayTransitionTime;
}
if (toPage == SCROLL_TO_CURRENT_PAGE) {
toPage = mWorkspace.getPageNearestToCenterOfScreen();
}
mWorkspace.snapToPage(toPage, duration, mZoomInInterpolator);
for (int i = 0; i < childCount; i++) {
final CellLayout cl = (CellLayout) mWorkspace.getChildAt(i);
boolean isCurrentPage = (i == toPage);
float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
float finalAlpha;
if (stateIsNormalHidden || stateIsOverviewHidden) {
finalAlpha = 0f;
} else if (stateIsNormal && mWorkspaceFadeInAdjacentScreens) {
finalAlpha = (i == toPage || i < customPageCount) ? 1f : 0f;
} else {
finalAlpha = 1f;
}
// If we are animating to/from the small state, then hide the side pages and fade the
// current page in
if (!mWorkspace.isSwitchingState()) {
if (workspaceToAllApps || allAppsToWorkspace) {
if (allAppsToWorkspace && isCurrentPage) {
initialAlpha = 0f;
} else if (!isCurrentPage) {
initialAlpha = finalAlpha = 0f;
}
cl.setShortcutAndWidgetAlpha(initialAlpha);
}
}
mOldAlphas[i] = initialAlpha;
mNewAlphas[i] = finalAlpha;
if (animated) {
mOldBackgroundAlphas[i] = cl.getBackgroundAlpha();
mNewBackgroundAlphas[i] = finalBackgroundAlpha;
} else {
cl.setBackgroundAlpha(finalBackgroundAlpha);
cl.setShortcutAndWidgetAlpha(finalAlpha);
}
}
final View searchBar = mLauncher.getOrCreateQsbBar();
final View overviewPanel = mLauncher.getOverviewPanel();
final View hotseat = mLauncher.getHotseat();
final View pageIndicator = mWorkspace.getPageIndicator();
if (animated) {
LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(mWorkspace);
scale.scaleX(mNewScale)
.scaleY(mNewScale)
.translationY(finalWorkspaceTranslationY)
.setDuration(duration)
.setInterpolator(mZoomInInterpolator);
mStateAnimator.play(scale);
for (int index = 0; index < childCount; index++) {
final int i = index;
final CellLayout cl = (CellLayout) mWorkspace.getChildAt(i);
float currentAlpha = cl.getShortcutsAndWidgets().getAlpha();
if (mOldAlphas[i] == 0 && mNewAlphas[i] == 0) {
cl.setBackgroundAlpha(mNewBackgroundAlphas[i]);
cl.setShortcutAndWidgetAlpha(mNewAlphas[i]);
} else {
if (layerViews != null) {
layerViews.put(cl, LauncherStateTransitionAnimation.BUILD_LAYER);
}
if (mOldAlphas[i] != mNewAlphas[i] || currentAlpha != mNewAlphas[i]) {
LauncherViewPropertyAnimator alphaAnim =
new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
alphaAnim.alpha(mNewAlphas[i])
.setDuration(duration)
.setInterpolator(mZoomInInterpolator);
mStateAnimator.play(alphaAnim);
}
if (mOldBackgroundAlphas[i] != 0 ||
mNewBackgroundAlphas[i] != 0) {
ValueAnimator bgAnim =
LauncherAnimUtils.ofFloat(cl, 0f, 1f);
bgAnim.setInterpolator(mZoomInInterpolator);
bgAnim.setDuration(duration);
bgAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
public void onAnimationUpdate(float a, float b) {
cl.setBackgroundAlpha(
a * mOldBackgroundAlphas[i] +
b * mNewBackgroundAlphas[i]);
}
});
mStateAnimator.play(bgAnim);
}
}
}
Animator pageIndicatorAlpha = null;
if (pageIndicator != null) {
pageIndicatorAlpha = new LauncherViewPropertyAnimator(pageIndicator)
.alpha(finalHotseatAndPageIndicatorAlpha).withLayer();
pageIndicatorAlpha.addListener(new AlphaUpdateListener(pageIndicator,
accessibilityEnabled));
} else {
// create a dummy animation so we don't need to do null checks later
pageIndicatorAlpha = ValueAnimator.ofFloat(0, 0);
}
LauncherViewPropertyAnimator hotseatAlpha = new LauncherViewPropertyAnimator(hotseat)
.alpha(finalHotseatAndPageIndicatorAlpha);
hotseatAlpha.addListener(new AlphaUpdateListener(hotseat, accessibilityEnabled));
LauncherViewPropertyAnimator overviewPanelAlpha =
new LauncherViewPropertyAnimator(overviewPanel).alpha(finalOverviewPanelAlpha);
overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel,
accessibilityEnabled));
// For animation optimations, we may need to provide the Launcher transition
// with a set of views on which to force build layers in certain scenarios.
hotseat.setLayerType(View.LAYER_TYPE_HARDWARE, null);
overviewPanel.setLayerType(View.LAYER_TYPE_HARDWARE, null);
if (layerViews != null) {
// If layerViews is not null, we add these views, and indicate that
// the caller can manage layer state.
layerViews.put(hotseat, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER);
layerViews.put(overviewPanel, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER);
} else {
// Otherwise let the animator handle layer management.
hotseatAlpha.withLayer();
overviewPanelAlpha.withLayer();
}
if (workspaceToOverview) {
pageIndicatorAlpha.setInterpolator(new DecelerateInterpolator(2));
hotseatAlpha.setInterpolator(new DecelerateInterpolator(2));
overviewPanelAlpha.setInterpolator(null);
} else if (overviewToWorkspace) {
pageIndicatorAlpha.setInterpolator(null);
hotseatAlpha.setInterpolator(null);
overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2));
}
overviewPanelAlpha.setDuration(duration);
pageIndicatorAlpha.setDuration(duration);
hotseatAlpha.setDuration(duration);
// TODO: This should really be coordinated with the SearchDropTargetBar, otherwise the
// bar has no idea that it is hidden, and this has no idea what state the bar is
// actually in.
if (searchBar != null) {
LauncherViewPropertyAnimator searchBarAlpha = new LauncherViewPropertyAnimator(searchBar)
.alpha(finalSearchBarAlpha);
searchBarAlpha.addListener(new AlphaUpdateListener(searchBar, accessibilityEnabled));
searchBar.setLayerType(View.LAYER_TYPE_HARDWARE, null);
if (layerViews != null) {
// If layerViews is not null, we add these views, and indicate that
// the caller can manage layer state.
layerViews.put(searchBar, LauncherStateTransitionAnimation.BUILD_AND_SET_LAYER);
} else {
// Otherwise let the animator handle layer management.
searchBarAlpha.withLayer();
}
searchBarAlpha.setDuration(duration);
mStateAnimator.play(searchBarAlpha);
}
mStateAnimator.play(overviewPanelAlpha);
mStateAnimator.play(hotseatAlpha);
mStateAnimator.play(pageIndicatorAlpha);
mStateAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mStateAnimator = null;
}
});
} else {
overviewPanel.setAlpha(finalOverviewPanelAlpha);
AlphaUpdateListener.updateVisibility(overviewPanel, accessibilityEnabled);
hotseat.setAlpha(finalHotseatAndPageIndicatorAlpha);
AlphaUpdateListener.updateVisibility(hotseat, accessibilityEnabled);
if (pageIndicator != null) {
pageIndicator.setAlpha(finalHotseatAndPageIndicatorAlpha);
AlphaUpdateListener.updateVisibility(pageIndicator, accessibilityEnabled);
}
if (searchBar != null) {
searchBar.setAlpha(finalSearchBarAlpha);
AlphaUpdateListener.updateVisibility(searchBar, accessibilityEnabled);
}
mWorkspace.updateCustomContentVisibility();
mWorkspace.setScaleX(mNewScale);
mWorkspace.setScaleY(mNewScale);
mWorkspace.setTranslationY(finalWorkspaceTranslationY);
}
if (stateIsNormal) {
animateBackgroundGradient(0f, animated);
} else {
animateBackgroundGradient(mWorkspaceScrimAlpha, animated);
}
}
/**
* Reinitializes the arrays that we need for the animations on each page.
*/
private void reinitializeAnimationArrays() {
final int childCount = mWorkspace.getChildCount();
if (mLastChildCount == childCount) return;
mOldBackgroundAlphas = new float[childCount];
mOldAlphas = new float[childCount];
mNewBackgroundAlphas = new float[childCount];
mNewAlphas = new float[childCount];
}
/**
* Animates the background scrim.
* TODO(winsonc): Is there a better place for this?
*
* @param finalAlpha the final alpha for the background scrim
* @param animated whether or not to set the background alpha immediately
*/
private void animateBackgroundGradient(float finalAlpha, boolean animated) {
// Cancel any running background animations
cancelAnimator(mBackgroundFadeInAnimation);
cancelAnimator(mBackgroundFadeOutAnimation);
final DragLayer dragLayer = mLauncher.getDragLayer();
final float startAlpha = dragLayer.getBackgroundAlpha();
if (finalAlpha != startAlpha) {
if (animated) {
mBackgroundFadeOutAnimation =
LauncherAnimUtils.ofFloat(mWorkspace, startAlpha, finalAlpha);
mBackgroundFadeOutAnimation.addUpdateListener(
new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
dragLayer.setBackgroundAlpha(
((Float)animation.getAnimatedValue()).floatValue());
}
});
mBackgroundFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
mBackgroundFadeOutAnimation.setDuration(BACKGROUND_FADE_OUT_DURATION);
mBackgroundFadeOutAnimation.start();
} else {
dragLayer.setBackgroundAlpha(finalAlpha);
}
}
}
/**
* Cancels the current animation.
*/
private void cancelAnimation() {
cancelAnimator(mStateAnimator);
mStateAnimator = null;
}
/**
* Cancels the specified animation.
*/
private void cancelAnimator(Animator animator) {
if (animator != null) {
animator.setDuration(0);
animator.cancel();
}
}
}