summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNebojsa Cvetkovic <nebkat@gmail.com>2013-12-15 19:46:56 +0000
committerDanesh M <daneshm90@gmail.com>2014-01-24 16:25:19 -0800
commit7fc14e45774e3094ef3afdf391a13ad54df62a3e (patch)
treea50303eadf4dab290f99ef0a3c52446da2271827
parent04d59a5a3bda757080acf34a974474317e7a6ab3 (diff)
downloadandroid_packages_apps_Trebuchet-7fc14e45774e3094ef3afdf391a13ad54df62a3e.tar.gz
android_packages_apps_Trebuchet-7fc14e45774e3094ef3afdf391a13ad54df62a3e.tar.bz2
android_packages_apps_Trebuchet-7fc14e45774e3094ef3afdf391a13ad54df62a3e.zip
AppsCustomize: Overview panel
Change-Id: I5cfd1183194ee15d8bb18dcd2536a644c9599978
-rw-r--r--res/layout-land/launcher.xml8
-rw-r--r--res/layout-port/launcher.xml8
-rw-r--r--res/layout-sw720dp/launcher.xml8
-rw-r--r--res/layout/overview_panel.xml22
-rw-r--r--res/menu/apps_customize_sort_mode.xml11
-rw-r--r--res/values/cm_strings.xml9
-rw-r--r--res/xml/preferences_general.xml4
-rw-r--r--res/xml/preferences_headers.xml2
-rw-r--r--src/com/android/launcher3/AppFilter.java1
-rw-r--r--src/com/android/launcher3/AppsCustomizeLayout.java8
-rw-r--r--src/com/android/launcher3/AppsCustomizePagedView.java451
-rw-r--r--src/com/android/launcher3/DynamicGrid.java6
-rw-r--r--src/com/android/launcher3/Launcher.java112
-rw-r--r--src/com/android/launcher3/LauncherModel.java23
-rw-r--r--src/com/android/launcher3/Workspace.java2
15 files changed, 629 insertions, 46 deletions
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index 77ea2e9aa..3666b5986 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -50,10 +50,6 @@
android:id="@+id/qsb_bar"
layout="@layout/qsb_bar" />
- <include layout="@layout/overview_panel"
- android:id="@+id/overview_panel"
- android:visibility="gone" />
-
<!-- The Workspace cling must appear under the AppsCustomizePagedView below to ensure
that it is still visible during the transition to AllApps and doesn't overlay on
top of that view. -->
@@ -97,5 +93,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
+
+ <include layout="@layout/overview_panel"
+ android:id="@+id/overview_panel"
+ android:visibility="gone" />
</com.android.launcher3.DragLayer>
</FrameLayout>
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 6fbf7c717..11f74ba1d 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -44,10 +44,6 @@
android:layout_width="match_parent"
android:layout_height="match_parent" />
- <include layout="@layout/overview_panel"
- android:id="@+id/overview_panel"
- android:visibility="gone" />
-
<!-- Keep these behind the workspace so that they are not visible when
we go into AllApps -->
<include
@@ -102,5 +98,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
+
+ <include layout="@layout/overview_panel"
+ android:id="@+id/overview_panel"
+ android:visibility="gone" />
</com.android.launcher3.DragLayer>
</FrameLayout>
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 951e63a39..4f6aaf503 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -49,10 +49,6 @@
android:id="@+id/qsb_bar"
layout="@layout/qsb_bar" />
- <include layout="@layout/overview_panel"
- android:id="@+id/overview_panel"
- android:visibility="gone" />
-
<!-- Keep these behind the workspace so that they are not visible when
we go into AllApps -->
<include
@@ -97,5 +93,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible" />
+
+ <include layout="@layout/overview_panel"
+ android:id="@+id/overview_panel"
+ android:visibility="gone" />
</com.android.launcher3.DragLayer>
</FrameLayout>
diff --git a/res/layout/overview_panel.xml b/res/layout/overview_panel.xml
index 46e6e07e2..ada2b2483 100644
--- a/res/layout/overview_panel.xml
+++ b/res/layout/overview_panel.xml
@@ -50,6 +50,17 @@
android:fontFamily="sans-serif-condensed"
android:textAllCaps="true"
android:textSize="12sp" />
+ <TextView
+ android:id="@+id/sort_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/sort_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" />
<Space
android:layout_width="@dimen/overview_panel_buttonSpacing"
android:layout_height="wrap_content"/>
@@ -64,6 +75,17 @@
android:fontFamily="sans-serif-condensed"
android:textAllCaps="true"
android:textSize="12sp"/>
+ <TextView
+ android:id="@+id/filter_button"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/filter_button_text"
+ android:drawablePadding="4dp"
+ android:gravity="center_horizontal"
+ android:drawableTop="@drawable/widget_button"
+ android:fontFamily="sans-serif-condensed"
+ android:textAllCaps="true"
+ android:textSize="12sp"/>
<Space
android:layout_width="@dimen/overview_panel_buttonSpacing"
android:layout_height="wrap_content"/>
diff --git a/res/menu/apps_customize_sort_mode.xml b/res/menu/apps_customize_sort_mode.xml
new file mode 100644
index 000000000..cb5f8faff
--- /dev/null
+++ b/res/menu/apps_customize_sort_mode.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <group android:checkableBehavior="single">
+ <item android:id="@+id/sort_mode_title"
+ android:title="@string/sort_mode_title" />
+ <item android:id="@+id/sort_mode_launch_count"
+ android:title="@string/sort_mode_launch_count" />
+ <item android:id="@+id/sort_mode_install_time"
+ android:title="@string/sort_mode_install_time" />
+ </group>
+</menu> \ No newline at end of file
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index eb0db0dbc..05cb477dd 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -5,9 +5,18 @@
<!-- App version -->
<string name="application_version" translatable="false">1.0</string>
+ <!-- Strings for the customization mode -->
+ <!-- Text for sorting mode button -->
+ <string name="sort_button_text">Sort</string>
+ <!-- Text for filter button -->
+ <string name="filter_button_text">Filter</string>
<!-- Text for default screen button -->
<string name="default_screen_button_text">Default Screen</string>
+ <string name="sort_mode_title">Title</string>
+ <string name="sort_mode_launch_count">Launch Count</string>
+ <string name="sort_mode_install_time">Install Time</string>
+
<!-- Settings -->
<string name="preferences_title">Settings</string>
<!-- UI -->
diff --git a/res/xml/preferences_general.xml b/res/xml/preferences_general.xml
index 24010b361..58e8a9aea 100644
--- a/res/xml/preferences_general.xml
+++ b/res/xml/preferences_general.xml
@@ -15,11 +15,11 @@
-->
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.cyanogenmod.trebuchet"
+ xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher3"
android:key="ui_general"
android:title="@string/preferences_interface_general_title">
<CheckBoxPreference android:key="ui_general_large_icons"
android:title="@string/preferences_interface_general_large_icons_title"
android:summary="@string/preferences_interface_general_large_icons_summary"
android:defaultValue="@bool/preferences_interface_general_large_icons_default" />
-</PreferenceScreen> \ No newline at end of file
+</PreferenceScreen>
diff --git a/res/xml/preferences_headers.xml b/res/xml/preferences_headers.xml
index 303532e8f..367ef832a 100644
--- a/res/xml/preferences_headers.xml
+++ b/res/xml/preferences_headers.xml
@@ -28,7 +28,7 @@
android:title="@string/preferences_interface_dock_title" />
<header android:id="@+id/preferences_general_section"
- android:fragment="org.cyanogenmod.trebuchet.settings.SettingsActivity$GeneralFragment"
+ android:fragment="com.android.launcher3.settings.SettingsActivity$GeneralFragment"
android:title="@string/preferences_interface_general_title" />
<header android:id="@+id/preferences_application_section"
diff --git a/src/com/android/launcher3/AppFilter.java b/src/com/android/launcher3/AppFilter.java
index e01436d7a..81556856e 100644
--- a/src/com/android/launcher3/AppFilter.java
+++ b/src/com/android/launcher3/AppFilter.java
@@ -31,5 +31,4 @@ public abstract class AppFilter {
return null;
}
}
-
}
diff --git a/src/com/android/launcher3/AppsCustomizeLayout.java b/src/com/android/launcher3/AppsCustomizeLayout.java
index f811006ea..ea1c36a9c 100644
--- a/src/com/android/launcher3/AppsCustomizeLayout.java
+++ b/src/com/android/launcher3/AppsCustomizeLayout.java
@@ -28,6 +28,7 @@ import android.widget.FrameLayout;
public class AppsCustomizeLayout extends FrameLayout implements LauncherTransitionable,
Insettable {
+
private AppsCustomizePagedView mAppsCustomizePane;
private FrameLayout mContent;
@@ -65,6 +66,13 @@ public class AppsCustomizeLayout extends FrameLayout implements LauncherTransiti
mAppsCustomizePane = appsCustomizePane;
mContent = (FrameLayout) findViewById(R.id.apps_customize_content);
if (mAppsCustomizePane == null) throw new Resources.NotFoundException();
+
+ findViewById(R.id.page_indicator).setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mAppsCustomizePane.enterOverviewMode();
+ }
+ });
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
diff --git a/src/com/android/launcher3/AppsCustomizePagedView.java b/src/com/android/launcher3/AppsCustomizePagedView.java
index ace83f77e..34dd9294d 100644
--- a/src/com/android/launcher3/AppsCustomizePagedView.java
+++ b/src/com/android/launcher3/AppsCustomizePagedView.java
@@ -16,7 +16,10 @@
package com.android.launcher3;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.appwidget.AppWidgetHostView;
import android.appwidget.AppWidgetManager;
@@ -36,13 +39,16 @@ import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Process;
+import android.support.v4.view.ViewCompat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.GridLayout;
@@ -53,6 +59,7 @@ import com.android.launcher3.DropTarget.DragObject;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
@@ -157,6 +164,16 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
private ContentType mContentType = ContentType.Applications;
+ /**
+ * The different sort modes than can be used to order items.
+ */
+ public enum SortMode {
+ Title,
+ LaunchCount,
+ InstallTime
+ }
+ private SortMode mSortMode = SortMode.Title;
+
// Refs
private Launcher mLauncher;
private DragController mDragController;
@@ -188,12 +205,33 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private int mNumAppsPages;
private int mNumWidgetPages;
+ // Animation states
+ enum State { NORMAL, OVERVIEW};
+ private State mState = State.NORMAL;
+ private boolean mIsSwitchingState = false;
+
+ // 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);
@@ -226,6 +264,9 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private Rect mTmpRect = new Rect();
+ private float mOverviewModeShrinkFactor;
+ private int mOverviewModePageOffset;
+
// Used for drawing shortcut previews
BitmapCache mCachedShortcutPreviewBitmap = new BitmapCache();
PaintCache mCachedShortcutPreviewPaint = new PaintCache();
@@ -242,6 +283,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private boolean mInBulkBind;
private boolean mNeedToUpdatePageCountsAndInvalidateData;
+ private static boolean sAccessibilityEnabled;
+
public AppsCustomizePagedView(Context context, AttributeSet attrs) {
super(context, attrs);
mLayoutInflater = LayoutInflater.from(context);
@@ -282,6 +325,11 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
Context context = getContext();
Resources r = context.getResources();
setDragSlopeThreshold(r.getInteger(R.integer.config_appsCustomizeDragSlopeThreshold)/100f);
+ mOverviewModeShrinkFactor =
+ r.getInteger(R.integer.config_workspaceOverviewShrinkPercentage) / 100.0f;
+ mOverviewModePageOffset = r.getDimensionPixelSize(R.dimen.overview_mode_page_offset);
+
+ setMinScale(mOverviewModeShrinkFactor - 0.2f);
}
public void onFinishInflate() {
@@ -527,10 +575,22 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
}
+ /**
+ * Called directly from a CellLayout (not by the framework), after we've been added as a
+ * listener via setOnInterceptTouchEventListener(). This allows us to tell the CellLayout
+ * that it should intercept touch events, which is not something that is normally supported.
+ */
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return isInOverviewMode() || mIsSwitchingState;
+ }
+
public boolean onKey(View v, int keyCode, KeyEvent event) {
return FocusHelper.handleAppsCustomizeKeyEvent(v, keyCode, event);
}
+ private final Workspace.ZoomInInterpolator mZoomInInterpolator = new Workspace.ZoomInInterpolator();
+
/*
* PagedViewWithDraggableItems implementation
*/
@@ -903,6 +963,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
cancelAllTasks();
}
+ protected void onResume() {
+ AccessibilityManager am = (AccessibilityManager)
+ getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+ sAccessibilityEnabled = am.isEnabled();
+ }
+
public void clearAllWidgetPages() {
cancelAllTasks();
int count = getChildCount();
@@ -976,6 +1042,8 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
private void setupPage(AppsCustomizeCellLayout layout) {
layout.setGridSize(mCellCountX, mCellCountY);
+ layout.setOnClickListener(mLauncher);
+
// Note: We force a measure here to get around the fact that when we do layout calculations
// immediately after syncing, we don't have a proper width. That said, we already know the
// expected page width, so we can actually optimize by hiding all the TextView-based
@@ -988,6 +1056,18 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
setVisibilityOnChildren(layout, View.VISIBLE);
}
+ @Override
+ public void onChildViewAdded(View parent, View child) {
+ // For overview mode
+ if (child instanceof CellLayout) {
+ CellLayout cl = ((CellLayout) child);
+ cl.setOnInterceptTouchListener(this);
+ cl.setClickable(true);
+ cl.setImportantForAccessibility(ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO);
+ }
+ super.onChildViewAdded(parent, child);
+ }
+
public void syncAppsPageItems(int page, boolean immediate) {
// ensure that we have the right number of items on the pages
final boolean isRtl = isLayoutRtl();
@@ -1354,6 +1434,12 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
final boolean isRtl = isLayoutRtl();
super.screenScrolled(screenCenter);
+ enableHwLayersOnVisiblePages();
+
+ if (isInOverviewMode()) {
+ return;
+ }
+
for (int i = 0; i < getChildCount(); i++) {
View v = getPageAt(i);
if (v != null) {
@@ -1419,7 +1505,11 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
v.setTranslationX(translationX);
v.setScaleX(scale);
v.setScaleY(scale);
- v.setAlpha(alpha);
+ 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
@@ -1430,8 +1520,6 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
}
}
}
-
- enableHwLayersOnVisiblePages();
}
private void enableHwLayersOnVisiblePages() {
@@ -1456,26 +1544,316 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
for (int i = 0; i < screenCount; i++) {
final View layout = (View) getPageAt(i);
- if (!(leftScreen <= i && i <= rightScreen &&
- (i == forceDrawScreen || shouldDrawChild(layout)))) {
+ boolean enableLayer = leftScreen <= i && i <= rightScreen &&
+ (i == forceDrawScreen || shouldDrawChild(layout));
+ if (layout instanceof CellLayout) {
+ ((CellLayout) layout).enableHardwareLayer(enableLayer);
+ } else if (enableLayer) {
+ if (layout.getLayerType() != LAYER_TYPE_HARDWARE) {
+ layout.setLayerType(LAYER_TYPE_HARDWARE, null);
+ }
+ } else {
layout.setLayerType(LAYER_TYPE_NONE, null);
}
}
+ }
- for (int i = 0; i < screenCount; i++) {
- final View layout = (View) getPageAt(i);
+ protected void overScroll(float amount) {
+ acceleratedOverScroll(amount);
+ }
- if (leftScreen <= i && i <= rightScreen &&
- (i == forceDrawScreen || shouldDrawChild(layout))) {
- if (layout.getLayerType() != LAYER_TYPE_HARDWARE) {
- layout.setLayerType(LAYER_TYPE_HARDWARE, null);
+ public boolean isInOverviewMode() {
+ return mState == State.OVERVIEW;
+ }
+
+ public boolean enterOverviewMode() {
+ if (mTouchState != TOUCH_STATE_REST || !mIsDataReady || mContentType != ContentType.Applications) {
+ 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 = AppsCustomizePagedView.State.OVERVIEW;
+ if (!enable) {
+ finalState = AppsCustomizePagedView.State.NORMAL;
+ }
+
+ mLauncher.updateOverviewPanel();
+
+ Animator appsCustomizeAnim = getChangeStateAnimation(finalState, animated, 0, snapPage);
+ if (appsCustomizeAnim != null) {
+ onTransitionPrepare();
+ appsCustomizeAnim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator arg0) {
+ onTransitionEnd();
+ }
+ });
+ appsCustomizeAnim.start();
+ }
+ }
+
+ int getOverviewModeTranslationY() {
+ int childHeight = getNormalChildHeight();
+ int viewPortHeight = getViewportHeight();
+ int scaledChildHeight = (int) (mOverviewModeShrinkFactor * childHeight);
+
+ int offset = (viewPortHeight - scaledChildHeight) / 2;
+ int offsetDelta = mOverviewModePageOffset - offset + mInsets.top;
+
+ return offsetDelta;
+ }
+
+ private void setState(State state) {
+ mState = state;
+ updateAccessibilityFlags();
+ }
+
+ private void updateAccessibilityFlags() {
+ int accessible = mState == State.NORMAL ?
+ ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES :
+ ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
+ setImportantForAccessibility(accessible);
+ }
+
+ private void initAnimationArrays() {
+ 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];
+ }
+
+ Animator getChangeStateAnimation(final State state, boolean animated, int delay, int snapPage) {
+ if (mState == state) {
+ return null;
+ }
+
+ // Initialize animation arrays for the first time if necessary
+ initAnimationArrays();
+
+ AnimatorSet anim = animated ? LauncherAnimUtils.createAnimatorSet() : null;
+
+ final State oldState = mState;
+ final boolean oldStateIsNormal = (oldState == State.NORMAL);
+ final boolean oldStateIsOverview = (oldState == State.OVERVIEW);
+ setState(state);
+ final boolean stateIsNormal = (state == State.NORMAL);
+ final boolean stateIsOverview = (state == State.OVERVIEW);
+ float finalBackgroundAlpha = stateIsOverview ? 1.0f : 0f;
+ float finalPageIndicatorAlpha = stateIsOverview ? 0f : 1f;
+ float finalOverviewPanelAlpha = stateIsOverview ? 1f : 0f;
+ float finalWorkspaceTranslationY = stateIsOverview ? getOverviewModeTranslationY() : 0;
+
+ boolean workspaceToOverview = (oldStateIsNormal && stateIsOverview);
+ boolean overviewToWorkspace = (oldStateIsOverview && stateIsNormal);
+
+ mNewScale = 1.0f;
+
+ if (state != State.NORMAL) {
+ if (stateIsOverview) {
+ mNewScale = mOverviewModeShrinkFactor;
+ }
+ }
+
+ final int duration = getResources().getInteger(R.integer.config_overviewTransitionTime);
+
+ 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.setScaleX(1f);
+ cl.setScaleY(1f);
+ cl.setShortcutAndWidgetAlpha(1f);
+ }
+
+ mOldAlphas[i] = cl.getShortcutsAndWidgets().getAlpha();
+ 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);
+ }
+ }
+
+ final View overviewPanel = mLauncher.getOverviewPanel();
+ if (animated) {
+ anim.setDuration(duration);
+ LauncherViewPropertyAnimator scale = new LauncherViewPropertyAnimator(this);
+ scale.scaleX(mNewScale)
+ .scaleY(mNewScale)
+ .translationY(finalWorkspaceTranslationY)
+ .setInterpolator(mZoomInInterpolator);
+ anim.play(scale);
+ ValueAnimator invalidate = ValueAnimator.ofFloat(0f, 1f);
+ invalidate.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ invalidate();
+ }
+ });
+ anim.play(invalidate);
+ ObjectAnimator pageIndicatorAlpha = null;
+ if (getPageIndicator() != null) {
+ pageIndicatorAlpha = ObjectAnimator.ofFloat(getPageIndicator(), "alpha",
+ finalPageIndicatorAlpha);
+ }
+ ObjectAnimator overviewPanelAlpha = ObjectAnimator.ofFloat(overviewPanel,
+ "alpha", finalOverviewPanelAlpha);
+
+ overviewPanelAlpha.addListener(new AlphaUpdateListener(overviewPanel));
+
+ if (overviewToWorkspace) {
+ overviewPanelAlpha.setInterpolator(new DecelerateInterpolator(2));
+ }
+
+ if (getPageIndicator() != null) {
+ pageIndicatorAlpha.addListener(new AlphaUpdateListener(getPageIndicator()));
+ }
+
+ anim.play(overviewPanelAlpha);
+ anim.play(pageIndicatorAlpha);
+
+ for (int index = 0; index < getChildCount(); index++) {
+ final int i = index;
+
+ 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])
+ .setDuration(duration)
+ .setInterpolator(mZoomInInterpolator);
+ anim.play(a);
+ if (mOldBackgroundAlphas[i] != 0 ||
+ mNewBackgroundAlphas[i] != 0) {
+ ValueAnimator bgAnim =
+ LauncherAnimUtils.ofFloat(cl, 0f, 1f);
+ bgAnim.setInterpolator(mZoomInInterpolator);
+ bgAnim.addUpdateListener(new LauncherAnimatorUpdateListener() {
+ public void onAnimationUpdate(float a, float b) {
+ cl.setBackgroundAlpha(
+ a * mOldBackgroundAlphas[i] +
+ b * mNewBackgroundAlphas[i]);
+ }
+ });
+ anim.play(bgAnim);
+ }
}
}
+
+ anim.setStartDelay(delay);
+ } else {
+ overviewPanel.setAlpha(finalOverviewPanelAlpha);
+ AlphaUpdateListener.updateVisibility(overviewPanel);
+ if (getPageIndicator() != null) {
+ getPageIndicator().setAlpha(finalPageIndicatorAlpha);
+ AlphaUpdateListener.updateVisibility(getPageIndicator());
+ }
+ setScaleX(mNewScale);
+ setScaleY(mNewScale);
+ setTranslationY(finalWorkspaceTranslationY);
}
+ return anim;
}
- protected void overScroll(float amount) {
- acceleratedOverScroll(amount);
+ static class AlphaUpdateListener implements ValueAnimator.AnimatorUpdateListener, Animator.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);
+ }
}
/**
@@ -1495,6 +1873,49 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
mSaveInstanceStateItemIndex = -1;
}
+ private void onTransitionPrepare() {
+ mIsSwitchingState = true;
+
+ // Invalidate here to ensure that the pages are rendered during the state change transition.
+ invalidate();
+
+ enableHwLayersOnVisiblePages();
+ }
+
+ private void onTransitionEnd() {
+ mIsSwitchingState = false;
+ }
+
+ public Comparator<AppInfo> getComparatorForSortMode() {
+ switch (mSortMode) {
+ case Title:
+ return LauncherModel.getAppNameComparator();
+ case LaunchCount:
+ return LauncherModel.getAppLaunchCountComparator(mLauncher.getStats());
+ case InstallTime:
+ return LauncherModel.getAppInstallTimeComparator();
+ }
+ return LauncherModel.getAppNameComparator();
+ }
+
+ public void setSortMode(SortMode sortMode) {
+ if (mSortMode == sortMode) return;
+
+ mSortMode = sortMode;
+
+ Collections.sort(mApps, getComparatorForSortMode());
+
+ if (mContentType == ContentType.Applications) {
+ for (int i = 0; i < getChildCount(); i++) {
+ syncAppsPageItems(i, true);
+ }
+ }
+ }
+
+ public SortMode getSortMode() {
+ return mSortMode;
+ }
+
/*
* AllAppsView implementation
*/
@@ -1523,7 +1944,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
public void setApps(ArrayList<AppInfo> list) {
if (!DISABLE_ALL_APPS) {
mApps = list;
- Collections.sort(mApps, LauncherModel.getAppNameComparator());
+ Collections.sort(mApps, getComparatorForSortMode());
updatePageCountsAndInvalidateData();
}
}
@@ -1532,7 +1953,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen
int count = list.size();
for (int i = 0; i < count; ++i) {
AppInfo info = list.get(i);
- int index = Collections.binarySearch(mApps, info, LauncherModel.getAppNameComparator());
+ int index = Collections.binarySearch(mApps, info, getComparatorForSortMode());
if (index < 0) {
mApps.add(-(index + 1), info);
}
diff --git a/src/com/android/launcher3/DynamicGrid.java b/src/com/android/launcher3/DynamicGrid.java
index 5bbb9214f..c6f2cb282 100644
--- a/src/com/android/launcher3/DynamicGrid.java
+++ b/src/com/android/launcher3/DynamicGrid.java
@@ -480,6 +480,12 @@ class DeviceProfile {
pageIndicator.setLayoutParams(lp);
}
}
+
+ // Layout the apps customize
+ View appsCustomize = launcher.findViewById(R.id.apps_customize_pane_content);
+ lp = (FrameLayout.LayoutParams) appsCustomize.getLayoutParams();
+ lp.gravity = Gravity.CENTER;
+ appsCustomize.setLayoutParams(lp);
}
}
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 3d3b8b0d0..53fa329fb 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -76,6 +76,7 @@ import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
+import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
@@ -90,9 +91,11 @@ import android.view.accessibility.AccessibilityManager;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
+
import android.widget.Advanceable;
import android.widget.FrameLayout;
import android.widget.ImageView;
+import android.widget.PopupMenu;
import android.widget.TextView;
import android.widget.Toast;
@@ -916,6 +919,7 @@ public class Launcher extends Activity
}
mWorkspace.updateInteractionForState();
mWorkspace.onResume();
+ mAppsCustomizeContent.onResume();
}
@Override
@@ -984,7 +988,44 @@ public class Launcher extends Activity
startActivity(settings);
if (mWorkspace.isInOverviewMode()) {
mWorkspace.exitOverviewMode(false);
+ } else if (mAppsCustomizeContent.isInOverviewMode()) {
+ mAppsCustomizeContent.exitOverviewMode(false);
+ }
+ }
+
+ public void onClickSortModeButton(View v) {
+ final PopupMenu popupMenu = new PopupMenu(this, v);
+ final Menu menu = popupMenu.getMenu();
+ popupMenu.inflate(R.menu.apps_customize_sort_mode);
+ AppsCustomizePagedView.SortMode sortMode = mAppsCustomizeContent.getSortMode();
+ switch (sortMode) {
+ case Title:
+ menu.findItem(R.id.sort_mode_title).setChecked(true);
+ break;
+ case LaunchCount:
+ menu.findItem(R.id.sort_mode_launch_count).setChecked(true);
+ break;
+ case InstallTime:
+ menu.findItem(R.id.sort_mode_install_time).setChecked(true);
+ break;
}
+ popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ public boolean onMenuItemClick(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.sort_mode_title:
+ mAppsCustomizeContent.setSortMode(AppsCustomizePagedView.SortMode.Title);
+ break;
+ case R.id.sort_mode_install_time:
+ mAppsCustomizeContent.setSortMode(AppsCustomizePagedView.SortMode.InstallTime);
+ break;
+ case R.id.sort_mode_launch_count:
+ mAppsCustomizeContent.setSortMode(AppsCustomizePagedView.SortMode.LaunchCount);
+ break;
+ }
+ return true;
+ }
+ });
+ popupMenu.show();
}
public interface QSBScroller {
@@ -1160,6 +1201,7 @@ public class Launcher extends Activity
}
mOverviewPanel = findViewById(R.id.overview_panel);
+ mOverviewPanel.setAlpha(0f);
View widgetButton = findViewById(R.id.widget_button);
widgetButton.setOnClickListener(new OnClickListener() {
@Override
@@ -1195,7 +1237,24 @@ public class Launcher extends Activity
}
});
defaultScreenButton.setOnTouchListener(getHapticFeedbackTouchListener());
- mOverviewPanel.setAlpha(0f);
+
+ View sortButton = findViewById(R.id.sort_button);
+ sortButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ onClickSortModeButton(v);
+ }
+ });
+ sortButton.setOnTouchListener(getHapticFeedbackTouchListener());
+
+ View filterButton = findViewById(R.id.filter_button);
+ filterButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+
+ }
+ });
+ filterButton.setOnTouchListener(getHapticFeedbackTouchListener());
// Setup the workspace
mWorkspace.setHapticFeedbackEnabled(false);
@@ -1891,6 +1950,12 @@ public class Launcher extends Activity
} else {
mWorkspace.exitOverviewMode(true);
}
+ } else {
+ if (!mAppsCustomizeContent.isInOverviewMode()) {
+ mAppsCustomizeContent.enterOverviewMode();
+ } else {
+ mAppsCustomizeContent.exitOverviewMode(true);
+ }
}
return false;
}
@@ -2116,11 +2181,15 @@ public class Launcher extends Activity
@Override
public void onBackPressed() {
if (isAllAppsVisible()) {
- if (mAppsCustomizeContent.getContentType() ==
- AppsCustomizePagedView.ContentType.Applications) {
- showWorkspace(true);
+ if (mAppsCustomizeContent.isInOverviewMode()) {
+ mAppsCustomizeContent.exitOverviewMode(true);
} else {
- showOverviewMode(true);
+ if (mAppsCustomizeContent.getContentType() ==
+ AppsCustomizePagedView.ContentType.Applications) {
+ showWorkspace(true);
+ } else {
+ showOverviewMode(true);
+ }
}
} else if (mWorkspace.isInOverviewMode()) {
mWorkspace.exitOverviewMode(true);
@@ -2172,8 +2241,14 @@ public class Launcher extends Activity
}
if (v instanceof CellLayout) {
- if (mWorkspace.isInOverviewMode()) {
- mWorkspace.exitOverviewMode(mWorkspace.indexOfChild(v), true);
+ if (isAllAppsVisible()) {
+ if (mAppsCustomizeContent.isInOverviewMode()) {
+ mAppsCustomizeContent.exitOverviewMode(mAppsCustomizeContent.indexOfChild(v), true);
+ }
+ } else {
+ if (mWorkspace.isInOverviewMode()) {
+ mWorkspace.exitOverviewMode(mWorkspace.indexOfChild(v), true);
+ }
}
}
@@ -2671,6 +2746,25 @@ public class Launcher extends Activity
return mWorkspace;
}
+ public void updateOverviewPanel() {
+ View defaultScreenButton = mOverviewPanel.findViewById(R.id.default_screen_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);
+ widgetButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE);
+ wallpaperButton.setVisibility(!isAllAppsVisible() ? View.VISIBLE : View.GONE);
+ sortButton.setVisibility(isAllAppsVisible() ? View.VISIBLE : View.GONE);
+ // TODO: implement filtering
+ // filterButton.setVisibility(isAllAppsVisible() ? View.VISIBLE : View.GONE);
+ filterButton.setVisibility(View.GONE);
+
+ // Make sure overview panel is drawn above apps customize
+ mOverviewPanel.bringToFront();
+ }
+
public boolean isAllAppsVisible() {
return (mState == State.APPS_CUSTOMIZE) || (mOnResumeState == State.APPS_CUSTOMIZE);
}
@@ -3082,6 +3176,10 @@ public class Launcher extends Activity
void showAllApps(boolean animated, AppsCustomizePagedView.ContentType contentType,
boolean resetPageToZero) {
+ if (mAppsCustomizeContent.isInOverviewMode()) {
+ mAppsCustomizeContent.exitOverviewMode(false);
+ }
+
if (mState != State.WORKSPACE) return;
if (resetPageToZero) {
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 63ec2a257..e26d405bc 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -3094,14 +3094,21 @@ public class LauncherModel extends BroadcastReceiver {
}
};
}
- public static final Comparator<AppInfo> APP_INSTALL_TIME_COMPARATOR
- = new Comparator<AppInfo>() {
- public final int compare(AppInfo a, AppInfo b) {
- if (a.firstInstallTime < b.firstInstallTime) return 1;
- if (a.firstInstallTime > b.firstInstallTime) return -1;
- return 0;
- }
- };
+ public static final Comparator<AppInfo> getAppInstallTimeComparator() {
+ final Collator collator = Collator.getInstance();
+ return new Comparator<AppInfo>() {
+ public final int compare(AppInfo a, AppInfo b) {
+ if (a.firstInstallTime < b.firstInstallTime) return 1;
+ if (a.firstInstallTime > b.firstInstallTime) return -1;
+ int result = collator.compare(a.title.toString().trim(),
+ b.title.toString().trim());
+ if (result == 0) {
+ result = a.componentName.compareTo(b.componentName);
+ }
+ return result;
+ }
+ };
+ }
public static final Comparator<AppWidgetProviderInfo> getWidgetNameComparator() {
final Collator collator = Collator.getInstance();
return new Comparator<AppWidgetProviderInfo>() {
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index a5e2c10a1..12117f451 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -1962,6 +1962,8 @@ public class Workspace extends SmoothPagedView
finalState = Workspace.State.NORMAL;
}
+ mLauncher.updateOverviewPanel();
+
Animator workspaceAnim = getChangeStateAnimation(finalState, animated, 0, snapPage);
if (workspaceAnim != null) {
onTransitionPrepare();