summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNebojsa Cvetkovic <nebkat@gmail.com>2014-01-05 23:15:48 +0000
committerDanesh M <daneshm90@gmail.com>2014-01-24 16:25:19 -0800
commit78ffd65b78ce1e7c97fb408091d401aa6dd3193c (patch)
tree743145b03dffc3280bd3db7eaed80574cd49c301
parent233a1403274298f510bb57f02ffde54e40d3ec0b (diff)
downloadandroid_packages_apps_Trebuchet-78ffd65b78ce1e7c97fb408091d401aa6dd3193c.tar.gz
android_packages_apps_Trebuchet-78ffd65b78ce1e7c97fb408091d401aa6dd3193c.tar.bz2
android_packages_apps_Trebuchet-78ffd65b78ce1e7c97fb408091d401aa6dd3193c.zip
PagedView: Transition Effects
Change-Id: Ib134705952877165c334181548d577b3dceece68
-rw-r--r--res/layout/overview_panel.xml61
-rw-r--r--res/values/cm_arrays.xml33
-rw-r--r--res/values/cm_strings.xml2
-rw-r--r--res/values/dimens.xml2
-rw-r--r--res/values/preferences_defaults.xml2
-rw-r--r--src/com/android/launcher3/AppsCustomizePagedView.java201
-rw-r--r--src/com/android/launcher3/Launcher.java111
-rw-r--r--src/com/android/launcher3/PagedView.java419
-rw-r--r--src/com/android/launcher3/Workspace.java77
-rw-r--r--src/com/android/launcher3/settings/SettingsProvider.java2
10 files changed, 699 insertions, 211 deletions
diff --git a/res/layout/overview_panel.xml b/res/layout/overview_panel.xml
index ada2b2483..fad5ebe18 100644
--- a/res/layout/overview_panel.xml
+++ b/res/layout/overview_panel.xml
@@ -17,19 +17,44 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
- <TextView
- android:id="@+id/default_screen_button"
+
+ <LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:orientation="horizontal"
android:layout_gravity="center_horizontal|top"
- android:paddingTop="@dimen/overview_panel_top_padding"
- android:text="@string/default_screen_button_text"
- android:drawablePadding="4dp"
- android:drawableTop="@drawable/default_screen_button"
- android:gravity="center_horizontal"
- android:fontFamily="sans-serif-condensed"
- android:textAllCaps="true"
- android:textSize="12sp" />
+ android:paddingTop="@dimen/overview_panel_top_padding">
+
+ <TextView
+ android:id="@+id/default_screen_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
+ android:text="@string/default_screen_button_text"
+ android:drawablePadding="4dp"
+ android:drawableTop="@drawable/default_screen_button"
+ android:gravity="center_horizontal"
+ android:fontFamily="sans-serif-condensed"
+ android:textAllCaps="true"
+ android:textSize="12sp" />
+
+ <TextView
+ android:id="@+id/transition_effect_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
+ android:text="@string/transition_effect_button_text"
+ android:drawablePadding="4dp"
+ android:drawableTop="@drawable/wallpaper_button"
+ android:gravity="center_horizontal"
+ android:fontFamily="sans-serif-condensed"
+ android:textAllCaps="true"
+ android:textSize="12sp" />
+
+ </LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
@@ -43,6 +68,8 @@
android:id="@+id/wallpaper_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
android:text="@string/wallpaper_button_text"
android:drawablePadding="4dp"
android:drawableTop="@drawable/wallpaper_button"
@@ -54,6 +81,8 @@
android:id="@+id/sort_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
android:text="@string/sort_button_text"
android:drawablePadding="4dp"
android:drawableTop="@drawable/wallpaper_button"
@@ -61,13 +90,12 @@
android:fontFamily="sans-serif-condensed"
android:textAllCaps="true"
android:textSize="12sp" />
- <Space
- android:layout_width="@dimen/overview_panel_buttonSpacing"
- android:layout_height="wrap_content"/>
<TextView
android:id="@+id/widget_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
android:text="@string/widget_button_text"
android:drawablePadding="4dp"
android:gravity="center_horizontal"
@@ -79,6 +107,8 @@
android:id="@+id/filter_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
android:text="@string/filter_button_text"
android:drawablePadding="4dp"
android:gravity="center_horizontal"
@@ -86,13 +116,12 @@
android:fontFamily="sans-serif-condensed"
android:textAllCaps="true"
android:textSize="12sp"/>
- <Space
- android:layout_width="@dimen/overview_panel_buttonSpacing"
- android:layout_height="wrap_content"/>
<TextView
android:id="@+id/settings_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:paddingLeft="@dimen/overview_panel_button_spacing"
+ android:paddingRight="@dimen/overview_panel_button_spacing"
android:text="@string/settings_button_text"
android:drawablePadding="4dp"
android:gravity="center_horizontal"
diff --git a/res/values/cm_arrays.xml b/res/values/cm_arrays.xml
index 580e89317..5d614ab2d 100644
--- a/res/values/cm_arrays.xml
+++ b/res/values/cm_arrays.xml
@@ -10,4 +10,37 @@
<item>sans-serif-light</item>
<item>sans-serif-condensed</item>
</string-array>
+
+ <string-array name="transition_effect_entries">
+ <item>None</item>
+ <item>Zoom In</item>
+ <item>Zoom Out</item>
+ <item>Rotate Up</item>
+ <item>Rotate Down</item>
+ <item>Cube In</item>
+ <item>Cube Out</item>
+ <item>Stack</item>
+ <item>Accordion</item>
+ <item>Flip</item>
+ <item>Cylinder In</item>
+ <item>Cylinder Out</item>
+ <item>Carousel</item>
+ <item>Overview</item>
+ </string-array>
+ <string-array name="transition_effect_values">
+ <item>none</item>
+ <item>zoom-in</item>
+ <item>zoom-out</item>
+ <item>rotate-up</item>
+ <item>rotate-down</item>
+ <item>cube-in</item>
+ <item>cube-out</item>
+ <item>stack</item>
+ <item>accordion</item>
+ <item>flip</item>
+ <item>cylinder-in</item>
+ <item>cylinder-out</item>
+ <item>carousel</item>
+ <item>overview</item>
+ </string-array>
</resources> \ No newline at end of file
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 2dc3fa4bc..50b8bad73 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -12,6 +12,8 @@
<string name="filter_button_text">Filter</string>
<!-- Text for default screen button -->
<string name="default_screen_button_text">Default Screen</string>
+ <!-- Text for transition effect button -->
+ <string name="transition_effect_button_text">Scroll Effect</string>
<string name="sort_mode_title">Title</string>
<string name="sort_mode_launch_count">Launch Count</string>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 8176c8192..3b692a1d1 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -43,7 +43,7 @@
<dimen name="workspace_spring_loaded_page_spacing">15dp</dimen>
<dimen name="overview_panel_top_padding">20dp</dimen>
<dimen name="overview_panel_bottom_padding">50dp</dimen>
- <dimen name="overview_panel_buttonSpacing">60dp</dimen>
+ <dimen name="overview_panel_button_spacing">30dp</dimen>
<dimen name="overview_mode_page_offset">130dp</dimen>
<!-- QSB -->
diff --git a/res/values/preferences_defaults.xml b/res/values/preferences_defaults.xml
index 9fa44b27e..ebb1650f4 100644
--- a/res/values/preferences_defaults.xml
+++ b/res/values/preferences_defaults.xml
@@ -1,8 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<bool name="preferences_interface_homescreen_search_default">true</bool>
+ <string name="preferences_interface_homescreen_scrolling_transition_effect">none</string>
<bool name="preferences_interface_homescreen_scrolling_wallpaper_scroll_default">true</bool>
<bool name="preferences_interface_homescreen_scrolling_page_outlines_default">@bool/config_workspaceDefaultShowOutlines</bool>
+ <string name="preferences_interface_drawer_scrolling_transition_effect">stack</string>
<bool name="preferences_interface_general_icons_large_default">@bool/config_largeIcons</bool>
<string name="preferences_interface_general_icons_text_font_family_default">sans-serif-condensed</string>
<integer name="preferences_interface_general_icons_text_font_style_default">0</integer>
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index 34625dfd7..44f50b200 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -56,6 +56,7 @@ import android.widget.ImageView;
import android.widget.Toast;
import com.android.launcher3.DropTarget.DragObject;
+import com.android.launcher3.settings.SettingsProvider;
import java.util.ArrayList;
import java.util.Collections;
@@ -213,28 +214,15 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// Animation values
private float mNewScale;
private float[] mOldBackgroundAlphas;
- private float[] mOldTranslationXs;
- private float[] mOldTranslationYs;
- private float[] mOldScaleXs;
- private float[] mOldScaleYs;
private float[] mOldAlphas;
private float[] mNewBackgroundAlphas;
- private float[] mNewTranslationXs;
- private float[] mNewTranslationYs;
- private float[] mNewScaleXs;
- private float[] mNewScaleYs;
private float[] mNewAlphas;
// Relating to the scroll and overscroll effects
- Workspace.ZInterpolator mZInterpolator = new Workspace.ZInterpolator(0.5f);
- private static float CAMERA_DISTANCE = 6500;
- private static float TRANSITION_SCALE_FACTOR = 0.74f;
- private static float TRANSITION_PIVOT = 0.65f;
private static float TRANSITION_MAX_ROTATION = 22;
private static final float ALPHA_CUTOFF_THRESHOLD = 0.01f;
- private static final boolean PERFORM_OVERSCROLL_ROTATION = true;
- private AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
- private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
+ private boolean mOverscrollTransformsSet;
+ private float mLastOverscrollPivotX;
public static boolean DISABLE_ALL_APPS = false;
@@ -311,6 +299,10 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
// (top + bottom)
mFadeInAdjacentScreens = false;
+ TransitionEffect.setFromString(this, SettingsProvider.getString(context,
+ SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT,
+ R.string.preferences_interface_drawer_scrolling_transition_effect));
+
// Unless otherwise specified this view is important for accessibility.
if (getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
@@ -324,6 +316,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
Context context = getContext();
Resources r = context.getResources();
+ mCameraDistance = (int) CAMERA_DISTANCE;//r.getInteger(R.integer.config_cameraDistance);
setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
mOverviewModeShrinkFactor =
r.getInteger(R.integer.config_workspaceOverviewShrinkPercentage) / 100.0f;
@@ -1057,6 +1050,15 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
@Override
+ public void setChildAlpha(View child, float alpha) {
+ if (child instanceof CellLayout) {
+ ((CellLayout) child).getShortcutsAndWidgets().setAlpha(alpha);
+ } else {
+ child.setAlpha(alpha);
+ }
+ }
+
+ @Override
public void onChildViewAdded(View parent, View child) {
// For overview mode
if (child instanceof CellLayout) {
@@ -1068,6 +1070,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
super.onChildViewAdded(parent, child);
}
+ protected boolean shouldDrawChild(View child) {
+ return super.shouldDrawChild(child) && (mIsSwitchingState ||
+ !(child instanceof CellLayout) ||
+ ((CellLayout) child).getShortcutsAndWidgets().getAlpha() > 0);
+ }
+
public void syncAppsPageItems(int page, boolean immediate) {
// ensure that we have the right number of items on the pages
final boolean isRtl = isLayoutRtl();
@@ -1433,92 +1441,51 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
@Override
protected void screenScrolled(int screenCenter) {
final boolean isRtl = isLayoutRtl();
- super.screenScrolled(screenCenter);
+ mUseTransitionEffect = !isInOverviewMode() && !mIsSwitchingState;
+
+ super.screenScrolled(screenCenter);
enableHwLayersOnVisiblePages();
- if (isInOverviewMode()) {
- return;
- }
+ boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
- for (int i = 0; i < getChildCount(); i++) {
- View v = getPageAt(i);
- if (v != null) {
- float scrollProgress = getScrollProgress(screenCenter, v, i);
+ if (isInOverscroll) {
+ int index = 0;
+ float pivotX = 0f;
+ final float leftBiasedPivot = 0.35f;
+ final float rightBiasedPivot = 0.65f;
+ final int lowerIndex = 0;
+ final int upperIndex = getChildCount() - 1;
- float interpolatedProgress;
- float translationX;
- float maxScrollProgress = Math.max(0, scrollProgress);
- float minScrollProgress = Math.min(0, scrollProgress);
+ final boolean isLeftPage = mOverScrollX < 0;
+ index = (!isRtl && isLeftPage) || (isRtl && !isLeftPage) ? lowerIndex : upperIndex;
+ pivotX = isLeftPage ? rightBiasedPivot : leftBiasedPivot;
- if (isRtl) {
- translationX = maxScrollProgress * v.getMeasuredWidth();
- interpolatedProgress = mZInterpolator.getInterpolation(Math.abs(maxScrollProgress));
- } else {
- translationX = minScrollProgress * v.getMeasuredWidth();
- interpolatedProgress = mZInterpolator.getInterpolation(Math.abs(minScrollProgress));
- }
- float scale = (1 - interpolatedProgress) +
- interpolatedProgress * TRANSITION_SCALE_FACTOR;
-
- float alpha;
- if (isRtl && (scrollProgress > 0)) {
- alpha = mAlphaInterpolator.getInterpolation(1 - Math.abs(maxScrollProgress));
- } else if (!isRtl && (scrollProgress < 0)) {
- alpha = mAlphaInterpolator.getInterpolation(1 - Math.abs(scrollProgress));
- } else {
- // On large screens we need to fade the page as it nears its leftmost position
- alpha = mLeftScreenAlphaInterpolator.getInterpolation(1 - scrollProgress);
- }
-
- v.setCameraDistance(mDensity * CAMERA_DISTANCE);
- int pageWidth = v.getMeasuredWidth();
- int pageHeight = v.getMeasuredHeight();
-
- if (PERFORM_OVERSCROLL_ROTATION) {
- float xPivot = isRtl ? 1f - TRANSITION_PIVOT : TRANSITION_PIVOT;
- boolean isOverscrollingFirstPage = isRtl ? scrollProgress > 0 : scrollProgress < 0;
- boolean isOverscrollingLastPage = isRtl ? scrollProgress < 0 : scrollProgress > 0;
-
- if (i == 0 && isOverscrollingFirstPage) {
- // Overscroll to the left
- v.setPivotX(xPivot * pageWidth);
- v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
- scale = 1.0f;
- alpha = 1.0f;
- // On the first page, we don't want the page to have any lateral motion
- translationX = 0;
- } else if (i == getChildCount() - 1 && isOverscrollingLastPage) {
- // Overscroll to the right
- v.setPivotX((1 - xPivot) * pageWidth);
- v.setRotationY(-TRANSITION_MAX_ROTATION * scrollProgress);
- scale = 1.0f;
- alpha = 1.0f;
- // On the last page, we don't want the page to have any lateral motion.
- translationX = 0;
- } else {
- v.setPivotY(pageHeight / 2.0f);
- v.setPivotX(pageWidth / 2.0f);
- v.setRotationY(0f);
- }
- }
+ View v = getPageAt(index);
- v.setTranslationX(translationX);
- v.setScaleX(scale);
- v.setScaleY(scale);
- if (v instanceof CellLayout) {
- ((CellLayout) v).getShortcutsAndWidgets().setAlpha(alpha);
- } else {
- v.setAlpha(alpha);
- }
+ if (!mOverscrollTransformsSet || Float.compare(mLastOverscrollPivotX, pivotX) != 0) {
+ mOverscrollTransformsSet = true;
+ mLastOverscrollPivotX = pivotX;
+ v.setCameraDistance(mDensity * mCameraDistance);
+ v.setPivotX(v.getMeasuredWidth() * pivotX);
+ }
- // If the view has 0 alpha, we set it to be invisible so as to prevent
- // it from accepting touches
- if (alpha == 0) {
- v.setVisibility(INVISIBLE);
- } else if (v.getVisibility() != VISIBLE) {
- v.setVisibility(VISIBLE);
- }
+ float scrollProgress = getScrollProgress(screenCenter, v, index);
+ float rotation = -TRANSITION_MAX_ROTATION * scrollProgress;
+ v.setRotationY(rotation);
+ } else {
+ if (mOverscrollTransformsSet) {
+ mOverscrollTransformsSet = false;
+ View v0 = getPageAt(0);
+ View v1 = getPageAt(getChildCount() - 1);
+ v0.setRotationY(0);
+ v1.setRotationY(0);
+ v0.setCameraDistance(mDensity * mCameraDistance);
+ v1.setCameraDistance(mDensity * mCameraDistance);
+ v0.setPivotX(v0.getMeasuredWidth() / 2);
+ v1.setPivotX(v1.getMeasuredWidth() / 2);
+ v0.setPivotY(v0.getMeasuredHeight() / 2);
+ v1.setPivotY(v1.getMeasuredHeight() / 2);
}
}
}
@@ -1631,16 +1598,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
final int childCount = getChildCount();
if (mOldBackgroundAlphas != null) return;
mOldBackgroundAlphas = new float[childCount];
- mOldTranslationXs = new float[childCount];
- mOldTranslationYs = new float[childCount];
- mOldScaleXs = new float[childCount];
- mOldScaleYs = new float[childCount];
mOldAlphas = new float[childCount];
mNewBackgroundAlphas = new float[childCount];
- mNewTranslationXs = new float[childCount];
- mNewTranslationYs = new float[childCount];
- mNewScaleXs = new float[childCount];
- mNewScaleYs = new float[childCount];
mNewAlphas = new float[childCount];
}
@@ -1680,15 +1639,17 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
for (int i = 0; i < getChildCount(); i++) {
final CellLayout cl = (CellLayout) getChildAt(i);
- float translationX = 0f;
- float translationY = 0f;
- float scaleX = 1f;
- float scaleY = 1f;
float finalAlpha = 1f;
if (stateIsOverview) {
cl.setVisibility(VISIBLE);
cl.setTranslationX(0f);
+ cl.setTranslationY(0f);
+ cl.setPivotX(cl.getMeasuredWidth() * 0.5f);
+ cl.setPivotY(cl.getMeasuredHeight() * 0.5f);
+ cl.setRotation(0f);
+ cl.setRotationY(0f);
+ cl.setRotationX(0f);
cl.setScaleX(1f);
cl.setScaleY(1f);
cl.setShortcutAndWidgetAlpha(1f);
@@ -1698,22 +1659,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mNewAlphas[i] = finalAlpha;
if (animated) {
mOldBackgroundAlphas[i] = cl.getBackgroundAlpha();
- mOldTranslationXs[i] = cl.getTranslationX();
- mOldTranslationYs[i] = cl.getTranslationY();
- mOldScaleXs[i] = cl.getScaleX();
- mNewScaleXs[i] = cl.getScaleY();
-
mNewBackgroundAlphas[i] = finalBackgroundAlpha;
- mNewTranslationXs[i] = translationX;
- mNewTranslationYs[i] = translationY;
- mNewScaleXs[i] = scaleX;
- mNewScaleYs[i] = scaleY;
} else {
cl.setBackgroundAlpha(finalBackgroundAlpha);
- cl.setTranslationX(translationX);
- cl.setTranslationY(translationY);
- cl.setScaleX(scaleX);
- cl.setScaleY(scaleY);
cl.setShortcutAndWidgetAlpha(finalAlpha);
}
}
@@ -1762,23 +1710,10 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
final CellLayout cl = (CellLayout) getChildAt(i);
if (mOldAlphas[i] == 0 && mNewAlphas[i] == 0) {
cl.setBackgroundAlpha(mNewBackgroundAlphas[i]);
- cl.setTranslationX(mNewTranslationXs[i]);
- cl.setTranslationY(mNewTranslationYs[i]);
- cl.setScaleX(mNewScaleXs[i]);
- cl.setScaleY(mNewScaleYs[i]);
cl.getShortcutsAndWidgets().setAlpha(mNewAlphas[i]);
} else {
- LauncherViewPropertyAnimator a = new LauncherViewPropertyAnimator(cl);
- a.translationX(mNewTranslationXs[i])
- .translationY(mNewTranslationYs[i])
- .scaleX(mNewScaleXs[i])
- .scaleY(mNewScaleYs[i])
- .setDuration(duration)
- .setInterpolator(mZoomInInterpolator);
- anim.play(a);
- a = new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
- a.translationX(mNewTranslationXs[i])
- .alpha(mNewAlphas[i])
+ LauncherViewPropertyAnimator a = new LauncherViewPropertyAnimator(cl.getShortcutsAndWidgets());
+ a.alpha(mNewAlphas[i])
.setDuration(duration)
.setInterpolator(mZoomInInterpolator);
anim.play(a);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index bfd5271df..d0df9c371 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -29,6 +29,8 @@ import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityOptions;
+import android.app.AlertDialog;
+import android.app.Dialog;
import android.app.SearchManager;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
@@ -39,6 +41,7 @@ import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
@@ -111,7 +114,6 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
-import java.lang.reflect.Array;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collection;
@@ -271,6 +273,8 @@ public class Launcher extends Activity
private Bundle mSavedInstanceState;
+ private Dialog mTransitionEffectDialog;
+
private LauncherModel mModel;
private IconCache mIconCache;
private boolean mUserPresent = true;
@@ -1029,6 +1033,88 @@ public class Launcher extends Activity
popupMenu.show();
}
+ public void onClickTransitionEffectButton(View v) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.transition_effect_button_text);
+
+ if (isAllAppsVisible()) {
+ mAppsCustomizeContent.exitOverviewMode(true);
+ } else {
+ mWorkspace.exitOverviewMode(true);
+ }
+
+ final PagedView pagedView = isAllAppsVisible() ? mAppsCustomizeContent : mWorkspace;
+ final PagedView.TransitionEffect oldEffect = pagedView.getTransitionEffect();
+ final String oldEffectName = oldEffect != null ? oldEffect.getName() :
+ PagedView.TransitionEffect.TRANSITION_EFFECT_NONE;
+
+ final String[] entries = getResources().getStringArray(R.array.transition_effect_entries);
+ final String[] values = getResources().getStringArray(R.array.transition_effect_values);
+
+ int selected = -1;
+ for (int i = values.length - 1; i >= 0; i--) {
+ if (values[i].equals(oldEffectName)) {
+ selected = i;
+ break;
+ }
+ }
+
+ builder.setSingleChoiceItems(entries, selected, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ String effect = values[which];
+ PagedView.TransitionEffect.setFromString(pagedView, effect);
+
+ final int currentPage = pagedView.getNextPage();
+ final int nextPage = currentPage + (currentPage != pagedView.getPageCount() - 1 ? 1 : -1);
+
+
+ pagedView.snapToPageImmediately(currentPage);
+ pagedView.snapToPage(nextPage, new Runnable() {
+ @Override
+ public void run() {
+ pagedView.snapToPage(currentPage);
+ }
+ });
+ }
+ })
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ PagedView.TransitionEffect effect = pagedView.getTransitionEffect();
+ String name = effect != null ? effect.getName() : PagedView.TransitionEffect.TRANSITION_EFFECT_NONE;
+
+ SettingsProvider.get(Launcher.this).edit()
+ .putString(!isAllAppsVisible() ?
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT :
+ SettingsProvider.SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT, name)
+ .commit();
+
+ dialog.dismiss();
+ }
+ })
+ .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ pagedView.setTransitionEffect(oldEffect);
+ }
+ })
+ .setOnDismissListener(new DialogInterface.OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ mTransitionEffectDialog = null;
+ }
+ });
+ mTransitionEffectDialog = builder.create();
+ mTransitionEffectDialog.show();
+ mTransitionEffectDialog.setCanceledOnTouchOutside(true);
+ mTransitionEffectDialog.getWindow().getDecorView().setAlpha(0.6f);
+ }
+
public interface QSBScroller {
public void setScrollY(int scrollY);
}
@@ -1239,11 +1325,20 @@ public class Launcher extends Activity
});
defaultScreenButton.setOnTouchListener(getHapticFeedbackTouchListener());
+ View transitionEffectButton = findViewById(R.id.transition_effect_button);
+ transitionEffectButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View arg0) {
+ onClickTransitionEffectButton(arg0);
+ }
+ });
+ transitionEffectButton.setOnTouchListener(getHapticFeedbackTouchListener());
+
View sortButton = findViewById(R.id.sort_button);
sortButton.setOnClickListener(new OnClickListener() {
@Override
- public void onClick(View v) {
- onClickSortModeButton(v);
+ public void onClick(View arg0) {
+ onClickSortModeButton(arg0);
}
});
sortButton.setOnTouchListener(getHapticFeedbackTouchListener());
@@ -1732,6 +1827,10 @@ public class Launcher extends Activity
// also will cancel mWaitingForResult.
closeSystemDialogs();
+ if (mTransitionEffectDialog != null) {
+ mTransitionEffectDialog.cancel();
+ }
+
final boolean alreadyOnHome = mHasFocus && ((intent.getFlags() &
Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT)
!= Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
@@ -2761,12 +2860,16 @@ public class Launcher extends Activity
public void updateOverviewPanel() {
View defaultScreenButton = mOverviewPanel.findViewById(R.id.default_screen_button);
+ View transitionEffectButton = mOverviewPanel.findViewById(R.id.transition_effect_button);
View widgetButton = mOverviewPanel.findViewById(R.id.widget_button);
View wallpaperButton = mOverviewPanel.findViewById(R.id.wallpaper_button);
View sortButton = mOverviewPanel.findViewById(R.id.sort_button);
View filterButton = mOverviewPanel.findViewById(R.id.filter_button);
- defaultScreenButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE);
+ PagedView pagedView = !isAllAppsVisible() ? mWorkspace : mAppsCustomizeContent;
+
+ defaultScreenButton.setVisibility((!isAllAppsVisible() && pagedView.getPageCount() > 1) ? View.VISIBLE : View.GONE);
+ transitionEffectButton.setVisibility(pagedView.getPageCount() > 1 ? View.VISIBLE : View.GONE);
widgetButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE);
wallpaperButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE);
sortButton.setVisibility(isAllAppsVisible() ? View.VISIBLE : View.GONE);
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index e982985f1..b70175ee8 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -47,12 +47,10 @@ import android.view.ViewParent;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.AnimationUtils;
-import android.view.animation.DecelerateInterpolator;
-import android.view.animation.Interpolator;
-import android.view.animation.LinearInterpolator;
+import android.view.animation.*;
import android.widget.Scroller;
+import java.lang.reflect.Array;
import java.util.ArrayList;
interface Page {
@@ -270,6 +268,17 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
protected int mFirstChildLeft;
+ private Runnable mDelayedSnapToPageRunnable;
+
+ // Relating to the scroll and overscroll effects
+ protected static float CAMERA_DISTANCE = 6500;
+ protected static final float TRANSITION_SCALE_FACTOR = 0.74f;
+ protected static final float TRANSITION_SCREEN_ROTATION = 12.5f;
+ protected int mCameraDistance;
+ private boolean mScrollTransformsSet;
+ protected TransitionEffect mTransitionEffect;
+ protected boolean mUseTransitionEffect = true;
+
public interface PageSwitchListener {
void onPageSwitch(View newPage, int newPageIndex);
}
@@ -597,6 +606,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
// a method that subclasses can override to add behavior
protected void onPageEndMoving() {
+ if (mDelayedSnapToPageRunnable != null) {
+ mDelayedSnapToPageRunnable.run();
+ mDelayedSnapToPageRunnable = null;
+ }
}
/**
@@ -997,20 +1010,68 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
}
}
+ public TransitionEffect getTransitionEffect() {
+ return mTransitionEffect;
+ }
+
+ public void setTransitionEffect(TransitionEffect effect) {
+ mTransitionEffect = effect;
+
+ // Reset scroll transforms
+ if (mScrollTransformsSet) {
+ for (int i = 0; i < getChildCount(); i++) {
+ View v = getPageAt(i);
+ if (v != null) {
+ v.setPivotX(v.getMeasuredWidth() * 0.5f);
+ v.setPivotY(v.getMeasuredHeight() * 0.5f);
+ v.setRotation(0);
+ v.setRotationX(0);
+ v.setRotationY(0);
+ v.setScaleX(1f);
+ v.setScaleY(1f);
+ v.setTranslationX(0f);
+ v.setTranslationY(0f);
+ v.setVisibility(VISIBLE);
+ setChildAlpha(v, 1f);
+ }
+ }
+
+ mScrollTransformsSet = false;
+ }
+ }
+
protected void screenScrolled(int screenCenter) {
boolean isInOverscroll = mOverScrollX < 0 || mOverScrollX > mMaxScrollX;
-
- if (mFadeInAdjacentScreens && !isInOverscroll) {
+ // Apply transition effect and adjacent screen fade if enabled
+ if (mFadeInAdjacentScreens || (mTransitionEffect != null && mUseTransitionEffect) || mScrollTransformsSet) {
for (int i = 0; i < getChildCount(); i++) {
- View child = getChildAt(i);
- if (child != null) {
- float scrollProgress = getScrollProgress(screenCenter, child, i);
- float alpha = 1 - Math.abs(scrollProgress);
- child.setAlpha(alpha);
+ View v = getPageAt(i);
+ if (v != null) {
+ float scrollProgress = getScrollProgress(screenCenter, v, i);
+ // Fade first to allow transition effects to override alpha
+ if (mFadeInAdjacentScreens && !isInOverscroll) {
+ float alpha = 1 - Math.abs(scrollProgress);
+ setChildAlpha(v, alpha);
+ }
+ if (mTransitionEffect != null && mUseTransitionEffect && !isInOverscroll) {
+ mTransitionEffect.screenScrolled(v, i, scrollProgress);
+ } else if (mScrollTransformsSet) {
+ v.setPivotX(v.getMeasuredWidth() * 0.5f);
+ v.setPivotY(v.getMeasuredHeight() * 0.5f);
+ v.setRotation(0);
+ v.setRotationX(0);
+ v.setRotationY(0);
+ v.setScaleX(1f);
+ v.setScaleY(1f);
+ v.setTranslationX(0f);
+ v.setTranslationY(0f);
+ v.setVisibility(VISIBLE);
+ setChildAlpha(v, 1f);
+ }
}
}
- invalidate();
}
+ mScrollTransformsSet = mTransitionEffect != null && mUseTransitionEffect && !isInOverscroll;
}
protected void enablePagedViewAnimations() {
@@ -1021,6 +1082,42 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
mAllowPagedViewAnimations = false;
}
+ /*
+ * 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);
+ }
+ }
+
+ protected void setChildAlpha(View child, float alpha) {
+ child.setAlpha(alpha);
+ }
+
@Override
public void onChildViewAdded(View parent, View child) {
// Update the page indicator, we don't update the page indicator as we
@@ -2153,6 +2250,14 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
snapToPage(whichPage, delta, duration);
}
+ protected void snapToPage(int whichPage, Runnable r) {
+ if (mDelayedSnapToPageRunnable != null) {
+ mDelayedSnapToPageRunnable.run();
+ }
+ mDelayedSnapToPageRunnable = r;
+ snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION);
+ }
+
protected void snapToPage(int whichPage) {
snapToPage(whichPage, PAGE_SNAP_ANIMATION_DURATION);
}
@@ -2815,4 +2920,294 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc
public boolean onHoverEvent(android.view.MotionEvent event) {
return true;
}
+
+ protected static abstract class TransitionEffect {
+ public static final String TRANSITION_EFFECT_NONE = "none";
+ public static final String TRANSITION_EFFECT_ZOOM_IN = "zoom-in";
+ public static final String TRANSITION_EFFECT_ZOOM_OUT = "zoom-out";
+ public static final String TRANSITION_EFFECT_ROTATE_UP = "rotate-up";
+ public static final String TRANSITION_EFFECT_ROTATE_DOWN = "rotate-down";
+ public static final String TRANSITION_EFFECT_CUBE_IN = "cube-in";
+ public static final String TRANSITION_EFFECT_CUBE_OUT = "cube-out";
+ public static final String TRANSITION_EFFECT_STACK = "stack";
+ public static final String TRANSITION_EFFECT_ACCORDION = "accordion";
+ public static final String TRANSITION_EFFECT_FLIP = "flip";
+ public static final String TRANSITION_EFFECT_CYLINDER_IN = "cylinder-in";
+ public static final String TRANSITION_EFFECT_CYLINDER_OUT = "cylinder-out";
+ public static final String TRANSITION_EFFECT_CAROUSEL = "carousel";
+ public static final String TRANSITION_EFFECT_OVERVIEW = "overview";
+
+ protected final PagedView mPagedView;
+ private final String mName;
+
+ public TransitionEffect(PagedView pagedView, String name) {
+ mPagedView = pagedView;
+ mName = name;
+ }
+
+ public abstract void screenScrolled(View v, int i, float scrollProgress);
+
+ public final String getName() {
+ return mName;
+ }
+
+ public static void setFromString(PagedView pagedView, String effect) {
+ if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_NONE)) {
+ pagedView.setTransitionEffect(null);
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_ZOOM_IN)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Zoom(pagedView, true));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_ZOOM_OUT)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Zoom(pagedView, false));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_CUBE_IN)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Cube(pagedView, true));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_CUBE_OUT)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Cube(pagedView, false));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_ROTATE_UP)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Rotate(pagedView, true));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_ROTATE_DOWN)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Rotate(pagedView, false));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_STACK)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Stack(pagedView));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_ACCORDION)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Accordion(pagedView));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_FLIP)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Flip(pagedView));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_CYLINDER_IN)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Cylinder(pagedView, true));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_CYLINDER_OUT)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Cylinder(pagedView, false));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_CAROUSEL)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Carousel(pagedView));
+ } else if (effect.equals(PagedView.TransitionEffect.TRANSITION_EFFECT_OVERVIEW)) {
+ pagedView.setTransitionEffect(new PagedView.TransitionEffect.Overview(pagedView));
+ }
+ }
+
+ public static class Zoom extends TransitionEffect {
+ private boolean mIn;
+
+ public Zoom(PagedView pagedView, boolean in) {
+ super(pagedView, in ? TRANSITION_EFFECT_ZOOM_IN : TRANSITION_EFFECT_ZOOM_OUT);
+ mIn = in;
+ }
+
+ @Override
+ public void screenScrolled(View v, int i, float scrollProgress) {
+ float scale = 1.0f + (mIn ? -0.2f : 0.1f) * Math.abs(scrollProgress);
+
+ // Extra translation to account for the increase in size
+ if (!mIn) {
+ float translationX = v.getMeasuredWidth() * 0.1f * -scrollProgress;
+ v.setTranslationX(translationX);
+ }
+
+ v.setScaleX(scale);
+ v.setScaleY(scale);
+ }
+ }
+
+ public static class Rotate extends TransitionEffect {
+ private boolean mUp;
+
+ public Rotate(PagedView pagedView, boolean up) {
+ super(pagedView, up ? TRANSITION_EFFECT_ROTATE_UP : TRANSITION_EFFECT_ROTATE_DOWN);
+ mUp = up;
+ }
+
+ @Override
+ public void screenScrolled(View v, int i, float scrollProgress) {
+ float rotation =
+ (mUp ? TRANSITION_SCREEN_ROTATION : -TRANSITION_SCREEN_ROTATION) * scrollProgress;
+
+ float translationX = v.getMeasuredWidth() * scrollProgress;
+
+ float rotatePoint =
+ (v.getMeasuredWidth() * 0.5f) /
+ (float) Math.tan(Math.toRadians((double) (TRANSITION_SCREEN_ROTATION * 0.5f)));
+
+ v.setPivotX(v.getMeasuredWidth() * 0.5f);
+ if (mUp) {
+ v.setPivotY(-rotatePoint);
+ } else {
+ v.setPivotY(v.getMeasuredHeight() + rotatePoint);
+ }
+ v.setRotation(rotation);
+ v.setTranslationX(translationX);
+ }
+ }
+
+ public static class Cube extends TransitionEffect {
+ private boolean mIn;
+
+ public Cube(PagedView pagedView, boolean in) {
+ super(pagedView, in ? TRANSITION_EFFECT_CUBE_IN : TRANSITION_EFFECT_CUBE_OUT);
+ mIn = in;
+ }
+
+ @Override
+ public void screenScrolled(View v, int i, float scrollProgress) {
+ float rotation = (mIn ? 90.0f : -90.0f) * scrollProgress;
+
+ if (mIn) {
+ v.setCameraDistance(mPagedView.mDensity * PagedView.CAMERA_DISTANCE);
+ }
+
+ v.setPivotX(scrollProgress < 0 ? 0 : v.getMeasuredWidth());
+ v.setPivotY(v.getMeasuredHeight() * 0.5f);
+ v.setRotationY(rotation);
+ }
+ }
+
+ public static class Stack extends TransitionEffect {
+ private ZInterpolator mZInterpolator = new ZInterpolator(0.5f);
+ private DecelerateInterpolator mLeftScreenAlphaInterpolator = new DecelerateInterpolator(4);
+ protected AccelerateInterpolator mAlphaInterpolator = new AccelerateInterpolator(0.9f);
+
+ public Stack(PagedView pagedView) {
+ super(pagedView, TRANSITION_EFFECT_STACK);
+ }
+
+ @Override
+ public void screenScrolled(View v, int i, float scrollProgress) {
+ final boolean isRtl = mPagedView.isLayoutRtl();
+ float interpolatedProgress;
+ float translationX;
+ float maxScrollProgress = Math.max(0, scrollProgress);
+ float minScrollProgress = Math.min(0, scrollProgress);
+
+ if (mPagedView.isLayoutRtl()) {
+ translationX = maxScrollProgress * v.getMeasuredWidth();
+ interpolatedProgress = mZInterpolator.getInterpolation(Math.abs(maxScrollProgress));
+ } else {
+ translationX = minScrollProgress * v.getMeasuredWidth();
+ interpolatedProgress = mZInterpolator.getInterpolation(Math.abs(minScrollProgress));
+ }
+ float scale = (1 - interpolatedProgress) +
+ interpolatedProgress * TRANSITION_SCALE_FACTOR;
+
+ float alpha;
+ if (isRtl && (scrollProgress > 0)) {
+ alpha = mAlphaInterpolator.getInterpolation(1 - Math.abs(maxScrollProgress));
+ } else if (!isRtl && (scrollProgress < 0)) {
+ alpha = mAlphaInterpolator.getInterpolation(1 - Math.abs(scrollProgress));
+ } else {
+ // On large screens we need to fade the page as it nears its leftmost position
+ alpha = mLeftScreenAlphaInterpolator.getInterpolation(1 - scrollProgress);
+ }
+
+ v.setTranslationX(translationX);
+ v.setScaleX(scale);
+ v.setScaleY(scale);
+ if (v instanceof CellLayout) {
+ ((CellLayout) v).getShortcutsAndWidgets().setAlpha(alpha);
+ } else {
+ v.setAlpha(alpha);
+ }
+
+ // If the view has 0 alpha, we set it to be invisible so as to prevent
+ // it from accepting touches
+ if (alpha == 0) {
+ v.setVisibility(INVISIBLE);
+ } else if (v.getVisibility() != VISIBLE) {
+ v.setVisibility(VISIBLE);
+ }
+ }
+ }
+
+ public static class Accordion extends TransitionEffect {
+ public Accordion(PagedView pagedView) {
+ super(pagedView, TRANSITION_EFFECT_ACCORDION);
+ }
+
+ @Override
+ public void screenScrolled(View v, int i, float scrollProgress) {
+ float scale = 1.0f - Math.abs(scrollProgress);
+
+ v.setScaleX(scale);
+ v.setPivotX(scrollProgress < 0 ? 0 : v.getMeasuredWidth());
+ v.setPivotY(v.getMeasuredHeight() / 2f);
+ }
+ }
+
+ public static class Flip extends TransitionEffect {
+ public Flip(PagedView pagedView) {
+ super(pagedView, TRANSITION_EFFECT_FLIP);
+ }
+
+ @Override
+ public void screenScrolled(View v, int i, float scrollProgress) {
+ float rotation = -180.0f * Math.max(-1f, Math.min(1f, scrollProgress));
+
+ v.setCameraDistance(mPagedView.mDensity * PagedView.CAMERA_DISTANCE);
+ v.setPivotX(v.getMeasuredWidth() * 0.5f);
+ v.setPivotY(v.getMeasuredHeight() * 0.5f);
+ v.setRotationY(rotation);
+
+ if (scrollProgress >= -0.5f && scrollProgress <= 0.5f) {
+ v.setTranslationX(v.getMeasuredWidth() * scrollProgress);
+ if (v.getVisibility() != VISIBLE) {
+ v.setVisibility(VISIBLE);
+ }
+ } else {
+ v.setTranslationX(0f);
+ v.setVisibility(INVISIBLE);
+ }
+ }
+ }
+
+ public static class Cylinder extends TransitionEffect {
+ private boolean mIn;
+
+ public Cylinder(PagedView pagedView, boolean in) {
+ super(pagedView, in ? TRANSITION_EFFECT_CYLINDER_IN : TRANSITION_EFFECT_CYLINDER_OUT);
+ mIn = in;
+ }
+
+ @Override
+ public void screenScrolled(View v, int i, float scrollProgress) {
+ float rotation = (mIn ? TRANSITION_SCREEN_ROTATION : -TRANSITION_SCREEN_ROTATION) * scrollProgress;
+
+ v.setPivotX((scrollProgress + 1) * v.getMeasuredWidth() * 0.5f);
+ v.setPivotY(v.getMeasuredHeight() * 0.5f);
+ v.setRotationY(rotation);
+ }
+ }
+
+ public static class Carousel extends TransitionEffect {
+ public Carousel(PagedView pagedView) {
+ super(pagedView, TRANSITION_EFFECT_CAROUSEL);
+ }
+
+ @Override
+ public void screenScrolled(View v, int i, float scrollProgress) {
+ float rotation = 90.0f * scrollProgress;
+
+ v.setCameraDistance(mPagedView.mDensity * PagedView.CAMERA_DISTANCE);
+ v.setTranslationX(v.getMeasuredWidth() * scrollProgress);
+ v.setPivotX(!mPagedView.isLayoutRtl() ? 0f : v.getMeasuredWidth());
+ v.setPivotY(v.getMeasuredHeight() / 2);
+ v.setRotationY(-rotation);
+ }
+ }
+
+ public static class Overview extends TransitionEffect {
+ private AccelerateDecelerateInterpolator mScaleInterpolator = new AccelerateDecelerateInterpolator();
+
+ public Overview(PagedView pagedView) {
+ super(pagedView, TRANSITION_EFFECT_OVERVIEW);
+ }
+
+ @Override
+ public void screenScrolled(View v, int i, float scrollProgress) {
+ float scale = 1.0f - 0.1f *
+ mScaleInterpolator.getInterpolation(Math.min(0.3f, Math.abs(scrollProgress)) / 0.3f);
+
+ v.setPivotX(scrollProgress < 0 ? 0 : v.getMeasuredWidth());
+ v.setPivotY(v.getMeasuredHeight() * 0.5f);
+ v.setScaleX(scale);
+ v.setScaleY(scale);
+ mPagedView.setChildAlpha(v, scale);
+ }
+ }
+ }
}
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index f2a06e86c..ebe2e9af0 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -211,7 +211,7 @@ public class Workspace extends SmoothPagedView
WallpaperOffsetInterpolator mWallpaperOffset;
private boolean mScrollWallpaper;
private Runnable mDelayedResizeRunnable;
- private Runnable mDelayedSnapToPageRunnable;
+
private Point mDisplaySize = new Point();
private int mCameraDistance;
@@ -316,6 +316,9 @@ public class Workspace extends SmoothPagedView
mScrollWallpaper = SettingsProvider.getBoolean(context,
SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL,
R.bool.preferences_interface_homescreen_scrolling_wallpaper_scroll_default);
+ TransitionEffect.setFromString(this, SettingsProvider.getString(context,
+ SettingsProvider.SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT,
+ R.string.preferences_interface_homescreen_scrolling_transition_effect));
mLauncher = (Launcher) context;
final Resources res = getResources();
@@ -476,6 +479,11 @@ public class Workspace extends SmoothPagedView
}
@Override
+ public void setChildAlpha(View child, float alpha) {
+ ((CellLayout) child).setShortcutAndWidgetAlpha(alpha);
+ }
+
+ @Override
public void onChildViewAdded(View parent, View child) {
if (!(child instanceof CellLayout)) {
throw new IllegalArgumentException("A Workspace can only have CellLayout children.");
@@ -1101,10 +1109,6 @@ public class Workspace extends SmoothPagedView
mDelayedResizeRunnable = null;
}
- if (mDelayedSnapToPageRunnable != null) {
- mDelayedSnapToPageRunnable.run();
- mDelayedSnapToPageRunnable = null;
- }
if (mStripScreensOnPageStopMoving) {
stripEmptyScreens();
mStripScreensOnPageStopMoving = false;
@@ -1147,14 +1151,6 @@ public class Workspace extends SmoothPagedView
sp, mLauncher.getWindowManager(), mWallpaperManager);
}
- protected void snapToPage(int whichPage, Runnable r) {
- if (mDelayedSnapToPageRunnable != null) {
- mDelayedSnapToPageRunnable.run();
- }
- mDelayedSnapToPageRunnable = r;
- snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION);
- }
-
protected void snapToScreenId(long screenId, Runnable r) {
snapToPage(getPageIndexForScreenId(screenId), r);
}
@@ -1527,6 +1523,15 @@ public class Workspace extends SmoothPagedView
@Override
protected void screenScrolled(int screenCenter) {
final boolean isRtl = isLayoutRtl();
+
+ boolean isOnLastPageBeforeCustomContent = false;
+ if (hasCustomContent()) {
+ int customContentWidth = mWorkspaceScreens.get(CUSTOM_CONTENT_SCREEN_ID).getMeasuredWidth();
+ isOnLastPageBeforeCustomContent = (mOverScrollX < customContentWidth && (!hasCustomContent() || isLayoutRtl())) ||
+ (mOverScrollX > mMaxScrollX - customContentWidth && (!hasCustomContent() || !isLayoutRtl()));
+ }
+ mUseTransitionEffect = !isOnLastPageBeforeCustomContent && mState == State.NORMAL && !mIsSwitchingState;
+
super.screenScrolled(screenCenter);
updatePageAlphaValues(screenCenter);
@@ -1783,38 +1788,6 @@ public class Workspace extends SmoothPagedView
}
/*
- * 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 {
@@ -2100,6 +2073,20 @@ public class Workspace extends SmoothPagedView
float initialAlpha = cl.getShortcutsAndWidgets().getAlpha();
float finalAlpha = stateIsSmall ? 0f : 1f;
+ if (stateIsOverview) {
+ cl.setVisibility(VISIBLE);
+ cl.setTranslationX(0f);
+ cl.setTranslationY(0f);
+ cl.setPivotX(cl.getMeasuredWidth() * 0.5f);
+ cl.setPivotY(cl.getMeasuredHeight() * 0.5f);
+ cl.setRotation(0f);
+ cl.setRotationY(0f);
+ cl.setRotationX(0f);
+ cl.setScaleX(1f);
+ cl.setScaleY(1f);
+ cl.setShortcutAndWidgetAlpha(1f);
+ }
+
// If we are animating to/from the small state, then hide the side pages and fade the
// current page in
if (!mIsSwitchingState) {
diff --git a/src/com/android/launcher3/settings/SettingsProvider.java b/src/com/android/launcher3/settings/SettingsProvider.java
index 9c0a283ac..fb4c75056 100644
--- a/src/com/android/launcher3/settings/SettingsProvider.java
+++ b/src/com/android/launcher3/settings/SettingsProvider.java
@@ -26,8 +26,10 @@ public final class SettingsProvider {
public static final String SETTINGS_UI_HOMESCREEN_DEFAULT_SCREEN_ID = "ui_homescreen_default_screen_id";
public static final String SETTINGS_UI_HOMESCREEN_SEARCH = "ui_homescreen_search";
+ public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_TRANSITION_EFFECT = "ui_homescreen_scrolling_transition_effect";
public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_WALLPAPER_SCROLL = "ui_homescreen_scrolling_wallpaper_scroll";
public static final String SETTINGS_UI_HOMESCREEN_SCROLLING_PAGE_OUTLINES = "ui_homescreen_scrolling_page_outlines";
+ public static final String SETTINGS_UI_DRAWER_SCROLLING_TRANSITION_EFFECT = "ui_drawer_scrolling_transition_effect";
public static final String SETTINGS_UI_GENERAL_ICONS_LARGE = "ui_general_icons_large";
public static final String SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_FAMILY = "ui_general_icons_text_font";
public static final String SETTINGS_UI_GENERAL_ICONS_TEXT_FONT_STYLE = "ui_general_icons_text_font_style";