summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/drawable-hdpi/bg_appwidget_error.9.pngbin1285 -> 0 bytes
-rw-r--r--res/drawable-mdpi/bg_appwidget_error.9.pngbin794 -> 0 bytes
-rw-r--r--res/drawable-xhdpi/bg_appwidget_error.9.pngbin2387 -> 0 bytes
-rw-r--r--res/layout/apps_grid_icon_view.xml1
-rw-r--r--res/layout/apps_list_view.xml5
-rw-r--r--res/layout/apps_prediction_bar_icon_view.xml1
-rw-r--r--res/layout/appwidget_error.xml13
-rw-r--r--res/layout/widget_cell.xml25
-rw-r--r--res/values-v17/styles.xml6
-rw-r--r--res/values/colors.xml2
-rw-r--r--res/values/strings.xml54
-rw-r--r--res/values/styles.xml5
-rw-r--r--src/com/android/launcher3/AlphabeticalAppsList.java91
-rw-r--r--src/com/android/launcher3/AppsContainerRecyclerView.java65
-rw-r--r--src/com/android/launcher3/AppsContainerView.java234
-rw-r--r--src/com/android/launcher3/AppsGridAdapter.java15
-rw-r--r--src/com/android/launcher3/AppsRecyclerViewContainer.java61
-rw-r--r--src/com/android/launcher3/BaseContainerRecyclerView.java31
-rw-r--r--src/com/android/launcher3/BubbleTextView.java15
-rw-r--r--src/com/android/launcher3/CellLayout.java6
-rw-r--r--src/com/android/launcher3/DragController.java15
-rw-r--r--src/com/android/launcher3/DragLayer.java31
-rw-r--r--src/com/android/launcher3/HolographicOutlineHelper.java3
-rw-r--r--src/com/android/launcher3/LauncherModel.java34
-rw-r--r--src/com/android/launcher3/model/AppNameComparator.java105
-rw-r--r--src/com/android/launcher3/model/WidgetsAndShortcutNameComparator.java63
-rw-r--r--src/com/android/launcher3/widget/WidgetCell.java47
-rw-r--r--src/com/android/launcher3/widget/WidgetImageView.java68
-rw-r--r--src/com/android/launcher3/widget/WidgetsContainerView.java48
-rw-r--r--src/com/android/launcher3/widget/WidgetsListAdapter.java10
-rw-r--r--src/com/android/launcher3/widget/WidgetsModel.java18
31 files changed, 595 insertions, 477 deletions
diff --git a/res/drawable-hdpi/bg_appwidget_error.9.png b/res/drawable-hdpi/bg_appwidget_error.9.png
deleted file mode 100644
index 4da3195d4..000000000
--- a/res/drawable-hdpi/bg_appwidget_error.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-mdpi/bg_appwidget_error.9.png b/res/drawable-mdpi/bg_appwidget_error.9.png
deleted file mode 100644
index 493c0d454..000000000
--- a/res/drawable-mdpi/bg_appwidget_error.9.png
+++ /dev/null
Binary files differ
diff --git a/res/drawable-xhdpi/bg_appwidget_error.9.png b/res/drawable-xhdpi/bg_appwidget_error.9.png
deleted file mode 100644
index b792cc847..000000000
--- a/res/drawable-xhdpi/bg_appwidget_error.9.png
+++ /dev/null
Binary files differ
diff --git a/res/layout/apps_grid_icon_view.xml b/res/layout/apps_grid_icon_view.xml
index 67d7d50e7..7165f383d 100644
--- a/res/layout/apps_grid_icon_view.xml
+++ b/res/layout/apps_grid_icon_view.xml
@@ -25,6 +25,5 @@
android:paddingBottom="@dimen/apps_icon_top_bottom_padding"
android:focusable="true"
android:background="@drawable/focusable_view_bg"
- launcher:deferShadowGeneration="true"
launcher:iconDisplay="all_apps" />
diff --git a/res/layout/apps_list_view.xml b/res/layout/apps_list_view.xml
index 03ba646ee..6f9be05af 100644
--- a/res/layout/apps_list_view.xml
+++ b/res/layout/apps_list_view.xml
@@ -14,7 +14,8 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.launcher3.AppsRecyclerViewContainer
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/apps_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -101,4 +102,4 @@
android:src="@drawable/ic_search_grey" />
</FrameLayout>
-</FrameLayout> \ No newline at end of file
+</com.android.launcher3.AppsRecyclerViewContainer> \ No newline at end of file
diff --git a/res/layout/apps_prediction_bar_icon_view.xml b/res/layout/apps_prediction_bar_icon_view.xml
index 4a6f1574b..1e75d14b6 100644
--- a/res/layout/apps_prediction_bar_icon_view.xml
+++ b/res/layout/apps_prediction_bar_icon_view.xml
@@ -24,6 +24,5 @@
android:layout_weight="1"
android:focusable="true"
android:background="@drawable/focusable_view_bg"
- launcher:deferShadowGeneration="true"
launcher:iconDisplay="all_apps" />
diff --git a/res/layout/appwidget_error.xml b/res/layout/appwidget_error.xml
index 03d4ae424..708ece4e2 100644
--- a/res/layout/appwidget_error.xml
+++ b/res/layout/appwidget_error.xml
@@ -15,15 +15,12 @@
-->
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingTop="10dip"
- android:paddingBottom="10dip"
- android:paddingLeft="20dip"
- android:paddingRight="20dip"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:gravity="center"
- android:background="@drawable/bg_appwidget_error"
+ android:elevation="2dp"
+ android:background="@drawable/quantum_panel_dark"
android:textAppearance="?android:attr/textAppearanceMediumInverse"
- android:textColor="@color/appwidget_error_color"
+ android:textColor="@color/widgets_view_item_text_color"
android:text="@string/gadget_error_text"
/>
diff --git a/res/layout/widget_cell.xml b/res/layout/widget_cell.xml
index 500cf107f..7fefebaec 100644
--- a/res/layout/widget_cell.xml
+++ b/res/layout/widget_cell.xml
@@ -39,16 +39,15 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
- android:gravity="start"
- android:singleLine="true"
android:ellipsize="end"
android:fadingEdge="horizontal"
- android:textColor="@color/widgets_view_item_text_color"
- android:textSize="14sp"
- android:textAlignment="viewStart"
android:fontFamily="sans-serif-condensed"
+ android:gravity="start"
+ android:shadowColor="#B0000000"
android:shadowRadius="2.0"
- android:shadowColor="#B0000000" />
+ android:singleLine="true"
+ android:textColor="@color/widgets_view_item_text_color"
+ android:textSize="14sp" />
<!-- The original dimensions of the widget (can't be the same text as above due to different
style. -->
@@ -58,22 +57,18 @@
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
- android:layout_weight="0"
- android:gravity="start"
android:textColor="@color/widgets_view_item_text_color"
android:textSize="14sp"
- android:textAlignment="viewStart"
android:fontFamily="sans-serif-condensed"
android:shadowRadius="2.0"
android:shadowColor="#B0000000" />
</LinearLayout>
- <!-- The image of the widget. -->
+ <!-- The image of the widget. This view does not support padding. Any placement adjustment
+ should be done using margins. -->
<com.android.launcher3.widget.WidgetImageView
android:id="@+id/widget_preview"
- style="@style/WidgetImageView"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:scaleType="matrix" />
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ android:layout_weight="1" />
</com.android.launcher3.widget.WidgetCell> \ No newline at end of file
diff --git a/res/values-v17/styles.xml b/res/values-v17/styles.xml
deleted file mode 100644
index 3589e80ac..000000000
--- a/res/values-v17/styles.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <style name="WidgetImageView">
- <item name="android:paddingStart">@dimen/widget_preview_horizontal_padding</item>
- </style>
-</resources>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index 0ba55f326..1e89615af 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -27,8 +27,6 @@
<color name="focused_background">#80c6c5c5</color>
- <color name="appwidget_error_color">#FCCC</color>
-
<color name="workspace_icon_text_color">#FFF</color>
<color name="quantum_panel_text_color">#FF666666</color>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 51ad51f12..0fb5e3ad3 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -182,76 +182,76 @@
</string>
<!-- Strings for accessibility actions -->
- <!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] [DO NOT TRANSLATE] -->
- <string name="action_add_to_workspace">Add to home screen</string>
+ <!-- Accessibility action to add an app to workspace. [CHAR_LIMIT=30] -->
+ <string name="action_add_to_workspace">Add to Home screen</string>
- <!-- Accessibility action to move item to the current location. [CHAR_LIMIT=30] [DO NOT TRANSLATE] -->
+ <!-- Accessibility action to move item to the current location. [CHAR_LIMIT=30] -->
<string name="action_move_here">Move here</string>
- <!-- Accessibility confirmation for item added to workspace [DO NOT TRANSLATE] -->
+ <!-- Accessibility confirmation for item added to workspace. -->
<string name="item_added_to_workspace">Item added to home screen</string>
- <!-- Accessibility confirmation for item removed [DO NOT TRANSLATE] -->
+ <!-- Accessibility confirmation for item removed. -->
<string name="item_removed">Item removed</string>
- <!-- Accessibility action to move an item on the workspace. [CHAR_LIMIT=30] [DO NOT TRANSLATE] -->
- <string name="action_move">Move Item</string>
+ <!-- Accessibility action to move an item on the workspace. [CHAR_LIMIT=30] -->
+ <string name="action_move">Move item</string>
- <!-- Accessibility description to move item to empty cell. [DO NOT TRANSLATE] -->
+ <!-- Accessibility description to move item to empty cell. -->
<string name="move_to_empty_cell">Move to row <xliff:g id="number" example="1">%1$s</xliff:g> column <xliff:g id="number" example="1">%2$s</xliff:g></string>
- <!-- Accessibility description to move item inside a folder. [DO NOT TRANSLATE] -->
+ <!-- Accessibility description to move item inside a folder. -->
<string name="move_to_position">Move to position <xliff:g id="number" example="1">%1$s</xliff:g></string>
- <!-- Accessibility description to move item to the hotseat. [DO NOT TRANSLATE] -->
+ <!-- Accessibility description to move item to the hotseat. -->
<string name="move_to_hotseat_position">Move to favorites position <xliff:g id="number" example="1">%1$s</xliff:g></string>
- <!-- Accessibility confirmation for item move [DO NOT TRANSLATE]-->
+ <!-- Accessibility confirmation for item move. -->
<string name="item_moved">Item moved</string>
- <!-- Accessibility description to move item into an existing folder. [DO NOT TRANSLATE]-->
+ <!-- Accessibility description to move item into an existing folder. -->
<string name="add_to_folder">Add to folder: <xliff:g id="name" example="Games">%1$s</xliff:g></string>
- <!-- Accessibility description to move item into an existing folder containing an app. [DO NOT TRANSLATE]-->
+ <!-- Accessibility description to move item into an existing folder containing an app. -->
<string name="add_to_folder_with_app">Add to folder with <xliff:g id="name" example="Messenger">%1$s</xliff:g></string>
- <!-- Accessibility confirmation for item added to folder [DO NOT TRANSLATE] -->
+ <!-- Accessibility confirmation for item added to folder. -->
<string name="added_to_folder">Item added to folder</string>
- <!-- Accessibility description to create folder with another item. [DO NOT TRANSLATE] -->
+ <!-- Accessibility description to create folder with another item. -->
<string name="create_folder_with">Create folder with: <xliff:g id="name" example="Game">%1$s</xliff:g></string>
- <!-- Accessibility confirmation for folder created [DO NOT TRANSLATE] -->
+ <!-- Accessibility confirmation for folder created. -->
<string name="folder_created">Folder created</string>
- <!-- Accessibility action to move an item from folder to workspace. [CHAR_LIMIT=30] [DO NOT TRANSLATE] -->
- <string name="action_move_to_workspace">Move to home screen</string>
+ <!-- Accessibility action to move an item from folder to workspace. [CHAR_LIMIT=30] -->
+ <string name="action_move_to_workspace">Move to Home screen</string>
- <!-- Accessibility action to move an homescreen to the left. [CHAR_LIMIT=30] [DO NOT TRANSLATE] -->
+ <!-- Accessibility action to move an homescreen to the left. [CHAR_LIMIT=30] -->
<string name="action_move_screen_left">Move screen to left</string>
- <!-- Accessibility action to move an homescreen to the right. [CHAR_LIMIT=30] [DO NOT TRANSLATE] -->
+ <!-- Accessibility action to move an homescreen to the right. [CHAR_LIMIT=30] -->
<string name="action_move_screen_right">Move screen to right</string>
- <!-- Accessibility confirmation when a screen was moved [DO NOT TRANSLATE] -->
+ <!-- Accessibility confirmation when a screen was moved. -->
<string name="screen_moved">Screen moved</string>
- <!-- Accessibility action to resize a widget [DO NOT TRANSLATE] -->
+ <!-- Accessibility action to resize a widget. [CHAR_LIMIT=30] -->
<string name="action_resize">Resize</string>
- <!-- Accessibility action to increase width of a widget [DO NOT TRANSLATE] -->
+ <!-- Accessibility action to increase width of a widget. [CHAR_LIMIT=30] -->
<string name="action_increase_width">Increase width</string>
- <!-- Accessibility action to increase height of a widget [DO NOT TRANSLATE] -->
+ <!-- Accessibility action to increase height of a widget. [CHAR_LIMIT=30] -->
<string name="action_increase_height">Increase height</string>
- <!-- Accessibility action to decrease width of a widget [DO NOT TRANSLATE] -->
+ <!-- Accessibility action to decrease width of a widget. [CHAR_LIMIT=30] -->
<string name="action_decrease_width">Decrease width</string>
- <!-- Accessibility action to decrease height of a widget [DO NOT TRANSLATE] -->
+ <!-- Accessibility action to decrease height of a widget. [CHAR_LIMIT=30] -->
<string name="action_decrease_height">Decrease height</string>
- <!-- Accessibility confirmation for widget resize [DO NOT TRANSLATE]-->
+ <!-- Accessibility confirmation for widget resize. -->
<string name="widget_resized">Widget resized to width <xliff:g id="number" example="2">%1$s</xliff:g> height <xliff:g id="number" example="1">%2$s</xliff:g></string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index f95debeab..1496da994 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -86,9 +86,4 @@
<item name="ringOutset">4dp</item>
</style>
- <!-- Overridden in device overlays -->
- <style name="WidgetImageView">
- <item name="android:paddingLeft">@dimen/widget_preview_horizontal_padding</item>
- </style>
-
</resources>
diff --git a/src/com/android/launcher3/AlphabeticalAppsList.java b/src/com/android/launcher3/AlphabeticalAppsList.java
index eff7b0625..82aaeb99a 100644
--- a/src/com/android/launcher3/AlphabeticalAppsList.java
+++ b/src/com/android/launcher3/AlphabeticalAppsList.java
@@ -7,6 +7,7 @@ import android.util.Log;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.compat.UserHandleCompat;
import com.android.launcher3.compat.UserManagerCompat;
+import com.android.launcher3.model.AppNameComparator;
import java.text.Collator;
import java.util.ArrayList;
@@ -18,96 +19,6 @@ import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
-
-/**
- * A private class to manage access to an app name comparator.
- */
-class AppNameComparator {
- private final UserManagerCompat mUserManager;
- private final Collator mCollator;
- private final Comparator<AppInfo> mAppInfoComparator;
- private final Comparator<String> mSectionNameComparator;
- private HashMap<UserHandleCompat, Long> mUserSerialCache = new HashMap<>();
-
- public AppNameComparator(Context context) {
- mCollator = Collator.getInstance();
- mUserManager = UserManagerCompat.getInstance(context);
- mAppInfoComparator = new Comparator<AppInfo>() {
- public final int compare(AppInfo a, AppInfo b) {
- // Order by the title in the current locale
- int result = compareTitles(a.title.toString(), b.title.toString());
- if (result == 0) {
- // If two apps have the same title, then order by the component name
- result = a.componentName.compareTo(b.componentName);
- if (result == 0) {
- // If the two apps are the same component, then prioritize by the order that
- // the app user was created (prioritizing the main user's apps)
- if (UserHandleCompat.myUserHandle().equals(a.user)) {
- return -1;
- } else {
- Long aUserSerial = getAndCacheUserSerial(a.user);
- Long bUserSerial = getAndCacheUserSerial(b.user);
- return aUserSerial.compareTo(bUserSerial);
- }
- }
- }
- return result;
- }
- };
- mSectionNameComparator = new Comparator<String>() {
- @Override
- public int compare(String o1, String o2) {
- return compareTitles(o1, o2);
- }
- };
- }
-
- /**
- * Returns a locale-aware comparator that will alphabetically order a list of applications.
- */
- public Comparator<AppInfo> getAppInfoComparator() {
- // Clear the user serial cache so that we get serials as needed in the comparator
- mUserSerialCache.clear();
- return mAppInfoComparator;
- }
-
- /**
- * Returns a locale-aware comparator that will alphabetically order a list of section names.
- */
- public Comparator<String> getSectionNameComparator() {
- return mSectionNameComparator;
- }
-
- /**
- * Compares two titles with the same return value semantics as Comparator.
- */
- private int compareTitles(String titleA, String titleB) {
- // Ensure that we de-prioritize any titles that don't start with a linguistic letter or digit
- boolean aStartsWithLetter = Character.isLetterOrDigit(titleA.codePointAt(0));
- boolean bStartsWithLetter = Character.isLetterOrDigit(titleB.codePointAt(0));
- if (aStartsWithLetter && !bStartsWithLetter) {
- return -1;
- } else if (!aStartsWithLetter && bStartsWithLetter) {
- return 1;
- }
-
- // Order by the title in the current locale
- return mCollator.compare(titleA, titleB);
- }
-
- /**
- * Returns the user serial for this user, using a cached serial if possible.
- */
- private Long getAndCacheUserSerial(UserHandleCompat user) {
- Long userSerial = mUserSerialCache.get(user);
- if (userSerial == null) {
- userSerial = mUserManager.getSerialNumberForUser(user);
- mUserSerialCache.put(user, userSerial);
- }
- return userSerial;
- }
-}
-
/**
* The alphabetically sorted list of applications.
*/
diff --git a/src/com/android/launcher3/AppsContainerRecyclerView.java b/src/com/android/launcher3/AppsContainerRecyclerView.java
index 5b1da4b0c..31942b36d 100644
--- a/src/com/android/launcher3/AppsContainerRecyclerView.java
+++ b/src/com/android/launcher3/AppsContainerRecyclerView.java
@@ -122,30 +122,20 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
mApps = apps;
}
- @Override
- public void setAdapter(Adapter adapter) {
- // Register a change listener to update the scroll position state whenever the data set
- // changes.
- adapter.registerAdapterDataObserver(new AdapterDataObserver() {
- @Override
- public void onChanged() {
- post(new Runnable() {
- @Override
- public void run() {
- refreshCurScrollPosition();
- }
- });
- }
- });
- super.setAdapter(adapter);
- }
-
/**
* Sets the number of apps per row in this recycler view.
*/
public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow) {
mNumAppsPerRow = numAppsPerRow;
mNumPredictedAppsPerRow = numPredictedAppsPerRow;
+
+ DeviceProfile grid = LauncherAppState.getInstance().getDynamicGrid().getDeviceProfile();
+ RecyclerView.RecycledViewPool pool = getRecycledViewPool();
+ int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
+ pool.setMaxRecycledViews(AppsGridAdapter.PREDICTION_BAR_SPACER_TYPE, 1);
+ pool.setMaxRecycledViews(AppsGridAdapter.EMPTY_VIEW_TYPE, 1);
+ pool.setMaxRecycledViews(AppsGridAdapter.ICON_VIEW_TYPE, approxRows * mNumAppsPerRow);
+ pool.setMaxRecycledViews(AppsGridAdapter.SECTION_BREAK_VIEW_TYPE, approxRows);
}
public void updateBackgroundPadding(Drawable background) {
@@ -186,7 +176,20 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
*/
public void scrollToTop() {
scrollToPosition(0);
- updateScrollY(0);
+ }
+
+ /**
+ * Returns the current scroll position.
+ */
+ public int getScrollPosition() {
+ List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+ getCurScrollState(mScrollPosState, items);
+ if (mScrollPosState.rowIndex != -1) {
+ int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
+ return getPaddingTop() + (mScrollPosState.rowIndex * mScrollPosState.rowHeight) +
+ predictionBarHeight - mScrollPosState.rowTopOffset;
+ }
+ return 0;
}
@Override
@@ -357,7 +360,6 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
if (touchFraction <= predictionBarFraction) {
// Scroll to the top of the view, where the prediction bar is
layoutManager.scrollToPositionWithOffset(0, 0);
- updateScrollY(0);
return "";
}
}
@@ -376,9 +378,6 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
lastScrollSection = scrollSection;
}
- // We need to workaround the RecyclerView to get the right scroll position
- refreshCurScrollPosition();
-
// Scroll to the view at the position, anchored at the top of the screen. We call the scroll
// method on the LayoutManager directly since it is not exposed by RecyclerView.
layoutManager.scrollToPositionWithOffset(lastScrollSection.appItem.position, 0);
@@ -402,7 +401,6 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
int x;
int y;
int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
- boolean isRtl = Utilities.isRtl(getResources());
int rowCount = getNumRows();
getCurScrollState(mScrollPosState, items);
if (mScrollPosState.rowIndex != -1) {
@@ -413,7 +411,7 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
(int) (height / ((float) totalScrollHeight / height)));
// Calculate the position and size of the scroll bar
- if (isRtl) {
+ if (Utilities.isRtl(getResources())) {
x = mBackgroundPadding.left;
} else {
x = getWidth() - mBackgroundPadding.right - mScrollbarWidth;
@@ -442,11 +440,10 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
if (mFastScrollAlpha > 0f && !mFastScrollSectionName.isEmpty()) {
int x;
int y;
- boolean isRtl = Utilities.isRtl(getResources());
// Calculate the position for the fast scroller popup
Rect bgBounds = mFastScrollerBg.getBounds();
- if (isRtl) {
+ if (Utilities.isRtl(getResources())) {
x = mBackgroundPadding.left + getScrollBarSize();
} else {
x = getWidth() - getPaddingRight() - getScrollBarSize() - bgBounds.width();
@@ -492,20 +489,6 @@ public class AppsContainerRecyclerView extends BaseContainerRecyclerView {
}
/**
- * Forces a refresh of the scroll position to any scroll listener.
- */
- private void refreshCurScrollPosition() {
- List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
- getCurScrollState(mScrollPosState, items);
- if (mScrollPosState.rowIndex != -1) {
- int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
- int scrollY = getPaddingTop() + (mScrollPosState.rowIndex * mScrollPosState.rowHeight) +
- predictionBarHeight - mScrollPosState.rowTopOffset;
- updateScrollY(scrollY);
- }
- }
-
- /**
* Returns the current scroll state.
*/
private void getCurScrollState(ScrollPositionState stateOut,
diff --git a/src/com/android/launcher3/AppsContainerView.java b/src/com/android/launcher3/AppsContainerView.java
index 8709101f4..5ccb6c620 100644
--- a/src/com/android/launcher3/AppsContainerView.java
+++ b/src/com/android/launcher3/AppsContainerView.java
@@ -35,6 +35,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
@@ -47,12 +48,97 @@ import java.util.regex.Pattern;
/**
+ * Interface for controlling the header elevation in response to RecyclerView scroll.
+ */
+interface HeaderElevationController {
+ void onScroll(int scrollY);
+ void disable();
+}
+
+/**
+ * Implementation of the header elevation mechanism for pre-L devices. It simulates elevation
+ * by drawing a gradient under the header bar.
+ */
+final class HeaderElevationControllerV16 implements HeaderElevationController {
+
+ private final View mShadow;
+
+ private final float mScrollToElevation;
+
+ public HeaderElevationControllerV16(View header) {
+ Resources res = header.getContext().getResources();
+ mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
+
+ mShadow = new View(header.getContext());
+ mShadow.setBackground(new GradientDrawable(
+ GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0x44000000, 0x00000000}));
+ mShadow.setAlpha(0);
+
+ FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ res.getDimensionPixelSize(R.dimen.all_apps_header_shadow_height));
+ lp.topMargin = ((FrameLayout.LayoutParams) header.getLayoutParams()).height;
+
+ ((ViewGroup) header.getParent()).addView(mShadow, lp);
+ }
+
+ @Override
+ public void onScroll(int scrollY) {
+ float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
+ mScrollToElevation;
+ mShadow.setAlpha(elevationPct);
+ }
+
+ @Override
+ public void disable() {
+ ViewGroup parent = (ViewGroup) mShadow.getParent();
+ if (parent != null) {
+ parent.removeView(mShadow);
+ }
+ }
+}
+
+/**
+ * Implementation of the header elevation mechanism for L+ devices, which makes use of the native
+ * view elevation.
+ */
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+final class HeaderElevationControllerVL implements HeaderElevationController {
+
+ private final View mHeader;
+ private final float mMaxElevation;
+ private final float mScrollToElevation;
+
+ public HeaderElevationControllerVL(View header) {
+ mHeader = header;
+
+ Resources res = header.getContext().getResources();
+ mMaxElevation = res.getDimension(R.dimen.all_apps_header_max_elevation);
+ mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
+ }
+
+ @Override
+ public void onScroll(int scrollY) {
+ float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
+ mScrollToElevation;
+ float newElevation = mMaxElevation * elevationPct;
+ if (Float.compare(mHeader.getElevation(), newElevation) != 0) {
+ mHeader.setElevation(newElevation);
+ }
+ }
+
+ @Override
+ public void disable() { }
+}
+
+/**
* The all apps view container.
*/
public class AppsContainerView extends BaseContainerView implements DragSource, Insettable,
TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable,
AlphabeticalAppsList.FilterChangedCallback, AppsGridAdapter.PredictionBarSpacerCallbacks,
- View.OnTouchListener, View.OnClickListener, View.OnLongClickListener {
+ View.OnTouchListener, View.OnClickListener, View.OnLongClickListener,
+ ViewTreeObserver.OnPreDrawListener {
public static final boolean GRID_MERGE_SECTIONS = true;
@@ -96,8 +182,7 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
// Normal container insets
private int mContainerInset;
private int mPredictionBarHeight;
- // RecyclerView scroll position
- @Thunk int mRecyclerViewScrollY;
+ private int mLastRecyclerViewScrollPos = -1;
private CheckLongPressHelper mPredictionIconCheckForLongPress;
private View mPredictionIconUnderTouch;
@@ -266,14 +351,6 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
mAppsRecyclerView.setLayoutManager(mLayoutManager);
mAppsRecyclerView.setAdapter(mAdapter);
mAppsRecyclerView.setHasFixedSize(true);
- mAppsRecyclerView.setOnScrollListenerProxy(
- new BaseContainerRecyclerView.OnScrollToListener() {
- @Override
- public void onScrolledTo(int x, int y) {
- mRecyclerViewScrollY = y;
- onRecyclerViewScrolled();
- }
- });
if (mItemDecoration != null) {
mAppsRecyclerView.addItemDecoration(mItemDecoration);
}
@@ -283,9 +360,7 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
@Override
public void onBindPredictionBar() {
- if (!updatePredictionBarVisibility()) {
- return;
- }
+ updatePredictionBarVisibility();
List<AppInfo> predictedApps = mApps.getPredictedApps();
int childCount = mPredictionBarView.getChildCount();
@@ -401,6 +476,12 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
}
@Override
+ public boolean onPreDraw() {
+ synchronizeToRecyclerViewScrollPosition(mAppsRecyclerView.getScrollPosition());
+ return true;
+ }
+
+ @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return handleTouchEvent(ev);
}
@@ -600,7 +681,11 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
@Override
public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
- // Do nothing
+ // Register for a pre-draw listener to synchronize the recycler view scroll to other views
+ // in this container
+ if (!toWorkspace) {
+ getViewTreeObserver().addOnPreDrawListener(this);
+ }
}
@Override
@@ -620,18 +705,26 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
hideSearchField(false, false);
}
}
+ if (toWorkspace) {
+ getViewTreeObserver().removeOnPreDrawListener(this);
+ mLastRecyclerViewScrollPos = -1;
+ }
}
/**
* Updates the container when the recycler view is scrolled.
*/
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private void onRecyclerViewScrolled() {
- if (DYNAMIC_HEADER_ELEVATION) {
- mElevationController.onScroll(mRecyclerViewScrollY);
- }
+ private void synchronizeToRecyclerViewScrollPosition(int scrollY) {
+ if (mLastRecyclerViewScrollPos != scrollY) {
+ mLastRecyclerViewScrollPos = scrollY;
+ if (DYNAMIC_HEADER_ELEVATION) {
+ mElevationController.onScroll(scrollY);
+ }
- mPredictionBarView.setTranslationY(-mRecyclerViewScrollY + mAppsRecyclerView.getPaddingTop());
+ // Scroll the prediction bar with the contents of the recycler view
+ mPredictionBarView.setTranslationY(-scrollY + mAppsRecyclerView.getPaddingTop());
+ }
}
@Override
@@ -686,6 +779,19 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
}
}
break;
+ case MotionEvent.ACTION_MOVE:
+ if (mPredictionIconUnderTouch != null) {
+ float dist = (float) Math.hypot(x - mPredictionIconTouchDownPos.x,
+ y - mPredictionIconTouchDownPos.y);
+ if (dist > ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
+ if (mPredictionIconCheckForLongPress != null) {
+ mPredictionIconCheckForLongPress.cancelLongPress();
+ }
+ mPredictionIconCheckForLongPress = null;
+ mPredictionIconUnderTouch = null;
+ }
+ }
+ break;
case MotionEvent.ACTION_UP:
if (mBoundsCheckLastTouchDownPos.x > -1) {
ViewConfiguration viewConfig = ViewConfiguration.get(getContext());
@@ -728,8 +834,19 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
* Returns the predicted app in the prediction bar given a set of local coordinates.
*/
private View findPredictedAppAtCoordinate(int x, int y) {
- int[] coord = {x, y};
Rect hitRect = new Rect();
+
+ // Ensure we aren't hitting the search bar
+ int[] coord = {x, y};
+ Utilities.mapCoordInSelfToDescendent(mHeaderView, this, coord);
+ mHeaderView.getHitRect(hitRect);
+ if (hitRect.contains(coord[0], coord[1])) {
+ return null;
+ }
+
+ // Check against the children of the prediction bar
+ coord[0] = x;
+ coord[1] = y;
Utilities.mapCoordInSelfToDescendent(mPredictionBarView, this, coord);
for (int i = 0; i < mPredictionBarView.getChildCount(); i++) {
View child = mPredictionBarView.getChildAt(i);
@@ -843,79 +960,4 @@ public class AppsContainerView extends BaseContainerView implements DragSource,
private InputMethodManager getInputMethodManager() {
return (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
}
-
- private static interface HeaderElevationController {
-
- public void onScroll(int scrollY);
-
- public void disable();
- }
-
- private static final class HeaderElevationControllerV16 implements HeaderElevationController {
-
- private final View mShadow;
-
- private final float mScrollToElevation;
-
- public HeaderElevationControllerV16(View header) {
- Resources res = header.getContext().getResources();
- mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
-
- mShadow = new View(header.getContext());
- mShadow.setBackground(new GradientDrawable(
- GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0x44000000, 0x00000000}));
- mShadow.setAlpha(0);
-
- FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
- LayoutParams.MATCH_PARENT,
- res.getDimensionPixelSize(R.dimen.all_apps_header_shadow_height));
- lp.topMargin = ((FrameLayout.LayoutParams) header.getLayoutParams()).height;
-
- ((ViewGroup) header.getParent()).addView(mShadow, lp);
- }
-
- @Override
- public void onScroll(int scrollY) {
- float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
- mScrollToElevation;
- mShadow.setAlpha(elevationPct);
- }
-
- @Override
- public void disable() {
- ViewGroup parent = (ViewGroup) mShadow.getParent();
- if (parent != null) {
- parent.removeView(mShadow);
- }
- }
- }
-
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
- private static final class HeaderElevationControllerVL implements HeaderElevationController {
-
- private final View mHeader;
- private final float mMaxElevation;
- private final float mScrollToElevation;
-
- public HeaderElevationControllerVL(View header) {
- mHeader = header;
-
- Resources res = header.getContext().getResources();
- mMaxElevation = res.getDimension(R.dimen.all_apps_header_max_elevation);
- mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
- }
-
- @Override
- public void onScroll(int scrollY) {
- float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
- mScrollToElevation;
- float newElevation = mMaxElevation * elevationPct;
- if (Float.compare(mHeader.getElevation(), newElevation) != 0) {
- mHeader.setElevation(newElevation);
- }
- }
-
- @Override
- public void disable() { }
- }
}
diff --git a/src/com/android/launcher3/AppsGridAdapter.java b/src/com/android/launcher3/AppsGridAdapter.java
index d5a411e66..580930cf2 100644
--- a/src/com/android/launcher3/AppsGridAdapter.java
+++ b/src/com/android/launcher3/AppsGridAdapter.java
@@ -1,3 +1,18 @@
+/*
+ * 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.content.Context;
diff --git a/src/com/android/launcher3/AppsRecyclerViewContainer.java b/src/com/android/launcher3/AppsRecyclerViewContainer.java
new file mode 100644
index 000000000..cf4beca28
--- /dev/null
+++ b/src/com/android/launcher3/AppsRecyclerViewContainer.java
@@ -0,0 +1,61 @@
+/*
+ * 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.content.Context;
+import android.graphics.Bitmap;
+import android.util.AttributeSet;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.BubbleTextView.BubbleTextShadowHandler;
+
+public class AppsRecyclerViewContainer extends FrameLayout implements BubbleTextShadowHandler {
+
+ private final ClickShadowView mTouchFeedbackView;
+
+ public AppsRecyclerViewContainer(Context context) {
+ this(context, null);
+ }
+
+ public AppsRecyclerViewContainer(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public AppsRecyclerViewContainer(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ LauncherAppState app = LauncherAppState.getInstance();
+ DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
+
+ mTouchFeedbackView = new ClickShadowView(context);
+
+ // Make the feedback view large enough to hold the blur bitmap.
+ int size = grid.allAppsIconSizePx + mTouchFeedbackView.getExtraSize();
+ addView(mTouchFeedbackView, size, size);
+ }
+
+ @Override
+ public void setPressedIcon(BubbleTextView icon, Bitmap background) {
+ if (icon == null || background == null) {
+ mTouchFeedbackView.setBitmap(null);
+ mTouchFeedbackView.animate().cancel();
+ } else if (mTouchFeedbackView.setBitmap(background)) {
+ mTouchFeedbackView.alignWithIconView(icon, (ViewGroup) icon.getParent());
+ mTouchFeedbackView.animateShadow();
+ }
+ }
+}
diff --git a/src/com/android/launcher3/BaseContainerRecyclerView.java b/src/com/android/launcher3/BaseContainerRecyclerView.java
index 59e20ca2f..e52d88708 100644
--- a/src/com/android/launcher3/BaseContainerRecyclerView.java
+++ b/src/com/android/launcher3/BaseContainerRecyclerView.java
@@ -29,20 +29,11 @@ import com.android.launcher3.util.Thunk;
public class BaseContainerRecyclerView extends RecyclerView
implements RecyclerView.OnItemTouchListener {
- /**
- * Listener to get notified when the absolute scroll changes.
- */
- public interface OnScrollToListener {
- void onScrolledTo(int x, int y);
- }
-
private static final int SCROLL_DELTA_THRESHOLD_DP = 4;
/** Keeps the last known scrolling delta/velocity along y-axis. */
@Thunk int mDy = 0;
- @Thunk int mScrollY;
private float mDeltaThreshold;
- private OnScrollToListener mScrollToListener;
public BaseContainerRecyclerView(Context context) {
this(context, null);
@@ -68,20 +59,9 @@ public class BaseContainerRecyclerView extends RecyclerView
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
mDy = dy;
- mScrollY += dy;
- if (mScrollToListener != null) {
- mScrollToListener.onScrolledTo(0, mScrollY);
- }
}
}
- /**
- * Sets an additional scroll listener, only needed for LMR1 version of the support lib.
- */
- public void setOnScrollListenerProxy(OnScrollToListener listener) {
- mScrollToListener = listener;
- }
-
@Override
protected void onFinishInflate() {
super.onFinishInflate();
@@ -106,17 +86,6 @@ public class BaseContainerRecyclerView extends RecyclerView
}
/**
- * Updates the scroll position, used to workaround a RecyclerView issue with scrolling to
- * position.
- */
- protected void updateScrollY(int scrollY) {
- mScrollY = scrollY;
- if (mScrollToListener != null) {
- mScrollToListener.onScrolledTo(0, mScrollY);
- }
- }
-
- /**
* Returns whether this {@link MotionEvent} should trigger the scroll to be stopped.
*/
protected boolean shouldStopScroll(MotionEvent ev) {
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index d39e13976..3b3b9bf9f 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -34,6 +34,7 @@ import android.util.TypedValue;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
+import android.view.ViewParent;
import android.widget.TextView;
import com.android.launcher3.IconCache.IconLoadRequest;
@@ -276,9 +277,10 @@ public class BubbleTextView extends TextView {
}
// Only show the shadow effect when persistent pressed state is set.
- if (getParent() instanceof ShortcutAndWidgetContainer) {
- CellLayout layout = (CellLayout) getParent().getParent();
- layout.setPressedIcon(this, mPressedBackground);
+ ViewParent parent = getParent();
+ if (parent != null && parent.getParent() instanceof BubbleTextShadowHandler) {
+ ((BubbleTextShadowHandler) parent.getParent()).setPressedIcon(
+ this, mPressedBackground);
}
updateIconState();
@@ -520,4 +522,11 @@ public class BubbleTextView extends TextView {
}
}
}
+
+ /**
+ * Interface to be implemented by the grand parent to allow click shadow effect.
+ */
+ public static interface BubbleTextShadowHandler {
+ void setPressedIcon(BubbleTextView icon, Bitmap background);
+ }
}
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index a348008d8..57db805d8 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -47,6 +47,7 @@ import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.DecelerateInterpolator;
+import com.android.launcher3.BubbleTextView.BubbleTextShadowHandler;
import com.android.launcher3.FolderIcon.FolderRingAnimator;
import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
import com.android.launcher3.accessibility.FolderAccessibilityHelper;
@@ -61,7 +62,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.Stack;
-public class CellLayout extends ViewGroup {
+public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
public static final int WORKSPACE_ACCESSIBILITY_DRAG = 2;
public static final int FOLDER_ACCESSIBILITY_DRAG = 1;
@@ -409,7 +410,8 @@ public class CellLayout extends ViewGroup {
invalidate();
}
- void setPressedIcon(BubbleTextView icon, Bitmap background) {
+ @Override
+ public void setPressedIcon(BubbleTextView icon, Bitmap background) {
if (icon == null || background == null) {
mTouchFeedbackView.setBitmap(null);
mTouchFeedbackView.animate().cancel();
diff --git a/src/com/android/launcher3/DragController.java b/src/com/android/launcher3/DragController.java
index f5c29ae0a..2191455d5 100644
--- a/src/com/android/launcher3/DragController.java
+++ b/src/com/android/launcher3/DragController.java
@@ -174,19 +174,18 @@ public class DragController {
* @param dragInfo The data associated with the object that is being dragged
* @param dragAction The drag action: either {@link #DRAG_ACTION_MOVE} or
* {@link #DRAG_ACTION_COPY}
+ * @param viewImageBounds the position of the image inside the view
* @param dragRegion Coordinates within the bitmap b for the position of item being dragged.
* Makes dragging feel more precise, e.g. you can clip out a transparent border
*/
- public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo, int dragAction,
- Point extraPadding, float initialDragViewScale) {
+ public void startDrag(View v, Bitmap bmp, DragSource source, Object dragInfo,
+ Rect viewImageBounds, int dragAction, float initialDragViewScale) {
int[] loc = mCoordinatesTemp;
mLauncher.getDragLayer().getLocationInDragLayer(v, loc);
- int viewExtraPaddingLeft = extraPadding != null ? extraPadding.x : 0;
- int viewExtraPaddingTop = extraPadding != null ? extraPadding.y : 0;
- int dragLayerX = loc[0] + v.getPaddingLeft() + viewExtraPaddingLeft +
- (int) ((initialDragViewScale * bmp.getWidth() - bmp.getWidth()) / 2);
- int dragLayerY = loc[1] + v.getPaddingTop() + viewExtraPaddingTop +
- (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2);
+ int dragLayerX = loc[0] + viewImageBounds.left
+ + (int) ((initialDragViewScale * bmp.getWidth() - bmp.getWidth()) / 2);
+ int dragLayerY = loc[1] + viewImageBounds.top
+ + (int) ((initialDragViewScale * bmp.getHeight() - bmp.getHeight()) / 2);
startDrag(bmp, dragLayerX, dragLayerY, source, dragInfo, dragAction, null,
null, initialDragViewScale, false);
diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java
index e25e6152c..a85c42648 100644
--- a/src/com/android/launcher3/DragLayer.java
+++ b/src/com/android/launcher3/DragLayer.java
@@ -48,34 +48,35 @@ import java.util.ArrayList;
*/
public class DragLayer extends InsettableFrameLayout {
+ public static final int ANIMATION_END_DISAPPEAR = 0;
+ public static final int ANIMATION_END_FADE_OUT = 1;
+ public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
+
// Scrim color without any alpha component.
private static final int SCRIM_COLOR = Color.BLACK & 0x00FFFFFF;
+ private final int[] mTmpXY = new int[2];
+
@Thunk DragController mDragController;
- private int[] mTmpXY = new int[2];
private int mXDown, mYDown;
private Launcher mLauncher;
// Variables relating to resizing widgets
- private final ArrayList<AppWidgetResizeFrame> mResizeFrames =
- new ArrayList<AppWidgetResizeFrame>();
+ private final ArrayList<AppWidgetResizeFrame> mResizeFrames = new ArrayList<>();
private final boolean mIsRtl;
private AppWidgetResizeFrame mCurrentResizeFrame;
// Variables relating to animation of views after drop
private ValueAnimator mDropAnim = null;
private ValueAnimator mFadeOutAnim = null;
- private TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
+ private final TimeInterpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
@Thunk DragView mDropView = null;
@Thunk int mAnchorViewInitialScrollX = 0;
@Thunk View mAnchorView = null;
private boolean mHoverPointClosesFolder = false;
- private Rect mHitRect = new Rect();
- public static final int ANIMATION_END_DISAPPEAR = 0;
- public static final int ANIMATION_END_FADE_OUT = 1;
- public static final int ANIMATION_END_REMAIN_VISIBLE = 2;
+ private final Rect mHitRect = new Rect();
private TouchCompleteListener mTouchCompleteListener;
@@ -87,6 +88,7 @@ public class DragLayer extends InsettableFrameLayout {
private float mBackgroundAlpha = 0;
// Related to adjacent page hints
+ private final Rect mScrollChildPosition = new Rect();
private boolean mInScrollArea;
private boolean mShowPageHints;
private Drawable mLeftHoverDrawable;
@@ -914,6 +916,9 @@ public class DragLayer extends InsettableFrameLayout {
void showPageHints() {
mShowPageHints = true;
+ Workspace workspace = mLauncher.getWorkspace();
+ getDescendantRectRelativeToSelf(workspace.getChildAt(workspace.getChildCount() - 1),
+ mScrollChildPosition);
invalidate();
}
@@ -937,10 +942,6 @@ public class DragLayer extends InsettableFrameLayout {
if (mShowPageHints) {
Workspace workspace = mLauncher.getWorkspace();
int width = getMeasuredWidth();
- Rect childRect = new Rect();
- getDescendantRectRelativeToSelf(workspace.getChildAt(workspace.getChildCount() - 1),
- childRect);
-
int page = workspace.getNextPage();
CellLayout leftPage = (CellLayout) workspace.getChildAt(mIsRtl ? page + 1 : page - 1);
CellLayout rightPage = (CellLayout) workspace.getChildAt(mIsRtl ? page - 1 : page + 1);
@@ -948,15 +949,15 @@ public class DragLayer extends InsettableFrameLayout {
if (leftPage != null && leftPage.isDragTarget()) {
Drawable left = mInScrollArea && leftPage.getIsDragOverlapping() ?
mLeftHoverDrawableActive : mLeftHoverDrawable;
- left.setBounds(0, childRect.top,
- left.getIntrinsicWidth(), childRect.bottom);
+ left.setBounds(0, mScrollChildPosition.top,
+ left.getIntrinsicWidth(), mScrollChildPosition.bottom);
left.draw(canvas);
}
if (rightPage != null && rightPage.isDragTarget()) {
Drawable right = mInScrollArea && rightPage.getIsDragOverlapping() ?
mRightHoverDrawableActive : mRightHoverDrawable;
right.setBounds(width - right.getIntrinsicWidth(),
- childRect.top, width, childRect.bottom);
+ mScrollChildPosition.top, width, mScrollChildPosition.bottom);
right.draw(canvas);
}
}
diff --git a/src/com/android/launcher3/HolographicOutlineHelper.java b/src/com/android/launcher3/HolographicOutlineHelper.java
index 4a04d038a..5ff85d664 100644
--- a/src/com/android/launcher3/HolographicOutlineHelper.java
+++ b/src/com/android/launcher3/HolographicOutlineHelper.java
@@ -157,6 +157,9 @@ public class HolographicOutlineHelper {
Bitmap createMediumDropShadow(BubbleTextView view) {
Drawable icon = view.getIcon();
+ if (icon == null) {
+ return null;
+ }
Rect rect = icon.getBounds();
int bitmapWidth = (int) (rect.width() * view.getScaleX());
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 0b3049c2e..58e899aec 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -66,7 +66,6 @@ import com.android.launcher3.util.Thunk;
import java.lang.ref.WeakReference;
import java.net.URISyntaxException;
import java.security.InvalidParameterException;
-import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -3665,39 +3664,6 @@ public class LauncherModel extends BroadcastReceiver
return folderInfo;
}
- public static class WidgetAndShortcutNameComparator implements Comparator<Object> {
- private final AppWidgetManagerCompat mManager;
- private final PackageManager mPackageManager;
- private final HashMap<Object, String> mLabelCache;
- private final Collator mCollator;
-
- public WidgetAndShortcutNameComparator(Context context) {
- mManager = AppWidgetManagerCompat.getInstance(context);
- mPackageManager = context.getPackageManager();
- mLabelCache = new HashMap<Object, String>();
- mCollator = Collator.getInstance();
- }
- public final int compare(Object a, Object b) {
- String labelA, labelB;
- if (mLabelCache.containsKey(a)) {
- labelA = mLabelCache.get(a);
- } else {
- labelA = (a instanceof LauncherAppWidgetProviderInfo)
- ? Utilities.trim(mManager.loadLabel((LauncherAppWidgetProviderInfo) a))
- : Utilities.trim(((ResolveInfo) a).loadLabel(mPackageManager));
- mLabelCache.put(a, labelA);
- }
- if (mLabelCache.containsKey(b)) {
- labelB = mLabelCache.get(b);
- } else {
- labelB = (b instanceof LauncherAppWidgetProviderInfo)
- ? Utilities.trim(mManager.loadLabel((LauncherAppWidgetProviderInfo) b))
- : Utilities.trim(((ResolveInfo) b).loadLabel(mPackageManager));
- mLabelCache.put(b, labelB);
- }
- return mCollator.compare(labelA, labelB);
- }
- };
static boolean isValidProvider(AppWidgetProviderInfo provider) {
return (provider != null) && (provider.provider != null)
diff --git a/src/com/android/launcher3/model/AppNameComparator.java b/src/com/android/launcher3/model/AppNameComparator.java
new file mode 100644
index 000000000..706f7515d
--- /dev/null
+++ b/src/com/android/launcher3/model/AppNameComparator.java
@@ -0,0 +1,105 @@
+package com.android.launcher3.model;
+
+import android.content.Context;
+
+import com.android.launcher3.AppInfo;
+import com.android.launcher3.ItemInfo;
+import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.compat.UserManagerCompat;
+import java.text.Collator;
+import java.util.Comparator;
+import java.util.HashMap;
+
+/**
+ * Class to manage access to an app name comparator.
+ * <p>
+ * Used to sort application name in all apps view and widget tray view.
+ */
+public class AppNameComparator {
+ private final UserManagerCompat mUserManager;
+ private final Collator mCollator;
+ private final Comparator<ItemInfo> mAppInfoComparator;
+ private final Comparator<String> mSectionNameComparator;
+ private HashMap<UserHandleCompat, Long> mUserSerialCache = new HashMap<>();
+
+ public AppNameComparator(Context context) {
+ mCollator = Collator.getInstance();
+ mUserManager = UserManagerCompat.getInstance(context);
+ mAppInfoComparator = new Comparator<ItemInfo>() {
+
+ public final int compare(ItemInfo a, ItemInfo b) {
+ // Order by the title in the current locale
+ int result = compareTitles(a.title.toString(), b.title.toString());
+ if (result == 0 && a instanceof AppInfo && b instanceof AppInfo) {
+ AppInfo aAppInfo = (AppInfo) a;
+ AppInfo bAppInfo = (AppInfo) b;
+ // If two apps have the same title, then order by the component name
+ result = aAppInfo.componentName.compareTo(bAppInfo.componentName);
+ if (result == 0) {
+ // If the two apps are the same component, then prioritize by the order that
+ // the app user was created (prioritizing the main user's apps)
+ if (UserHandleCompat.myUserHandle().equals(a.user)) {
+ return -1;
+ } else {
+ Long aUserSerial = getAndCacheUserSerial(a.user);
+ Long bUserSerial = getAndCacheUserSerial(b.user);
+ return aUserSerial.compareTo(bUserSerial);
+ }
+ }
+ }
+ return result;
+ }
+ };
+ mSectionNameComparator = new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ return compareTitles(o1, o2);
+ }
+ };
+ }
+
+ /**
+ * Returns a locale-aware comparator that will alphabetically order a list of applications.
+ */
+ public Comparator<ItemInfo> getAppInfoComparator() {
+ // Clear the user serial cache so that we get serials as needed in the comparator
+ mUserSerialCache.clear();
+ return mAppInfoComparator;
+ }
+
+ /**
+ * Returns a locale-aware comparator that will alphabetically order a list of section names.
+ */
+ public Comparator<String> getSectionNameComparator() {
+ return mSectionNameComparator;
+ }
+
+ /**
+ * Compares two titles with the same return value semantics as Comparator.
+ */
+ private int compareTitles(String titleA, String titleB) {
+ // Ensure that we de-prioritize any titles that don't start with a linguistic letter or digit
+ boolean aStartsWithLetter = Character.isLetterOrDigit(titleA.codePointAt(0));
+ boolean bStartsWithLetter = Character.isLetterOrDigit(titleB.codePointAt(0));
+ if (aStartsWithLetter && !bStartsWithLetter) {
+ return -1;
+ } else if (!aStartsWithLetter && bStartsWithLetter) {
+ return 1;
+ }
+
+ // Order by the title in the current locale
+ return mCollator.compare(titleA, titleB);
+ }
+
+ /**
+ * Returns the user serial for this user, using a cached serial if possible.
+ */
+ private Long getAndCacheUserSerial(UserHandleCompat user) {
+ Long userSerial = mUserSerialCache.get(user);
+ if (userSerial == null) {
+ userSerial = mUserManager.getSerialNumberForUser(user);
+ mUserSerialCache.put(user, userSerial);
+ }
+ return userSerial;
+ }
+}
diff --git a/src/com/android/launcher3/model/WidgetsAndShortcutNameComparator.java b/src/com/android/launcher3/model/WidgetsAndShortcutNameComparator.java
new file mode 100644
index 000000000..7c4e80651
--- /dev/null
+++ b/src/com/android/launcher3/model/WidgetsAndShortcutNameComparator.java
@@ -0,0 +1,63 @@
+package com.android.launcher3.model;
+
+import android.appwidget.AppWidgetProviderInfo;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+
+import com.android.launcher3.LauncherAppWidgetProviderInfo;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.compat.AppWidgetManagerCompat;
+
+import java.text.Collator;
+import java.util.Comparator;
+import java.util.HashMap;
+
+public class WidgetsAndShortcutNameComparator implements Comparator<Object> {
+ private final AppWidgetManagerCompat mManager;
+ private final PackageManager mPackageManager;
+ private final HashMap<Object, String> mLabelCache;
+ private final Collator mCollator;
+
+ public WidgetsAndShortcutNameComparator(Context context) {
+ mManager = AppWidgetManagerCompat.getInstance(context);
+ mPackageManager = context.getPackageManager();
+ mLabelCache = new HashMap<Object, String>();
+ mCollator = Collator.getInstance();
+ }
+
+ @Override
+ public final int compare(Object a, Object b) {
+ String labelA, labelB;
+ if (mLabelCache.containsKey(a)) {
+ labelA = mLabelCache.get(a);
+ } else {
+ labelA = (a instanceof LauncherAppWidgetProviderInfo)
+ ? Utilities.trim(mManager.loadLabel((LauncherAppWidgetProviderInfo) a))
+ : Utilities.trim(((ResolveInfo) a).loadLabel(mPackageManager));
+ mLabelCache.put(a, labelA);
+ }
+ if (mLabelCache.containsKey(b)) {
+ labelB = mLabelCache.get(b);
+ } else {
+ labelB = (b instanceof LauncherAppWidgetProviderInfo)
+ ? Utilities.trim(mManager.loadLabel((LauncherAppWidgetProviderInfo) b))
+ : Utilities.trim(((ResolveInfo) b).loadLabel(mPackageManager));
+ mLabelCache.put(b, labelB);
+ }
+ int result = mCollator.compare(labelA, labelB);
+ if (result == 0 && a instanceof AppWidgetProviderInfo &&
+ b instanceof AppWidgetProviderInfo) {
+ AppWidgetProviderInfo aInfo = (AppWidgetProviderInfo) a;
+ AppWidgetProviderInfo bInfo = (AppWidgetProviderInfo) b;
+
+ // prioritize main user's widgets against work profile widgets.
+ if (aInfo.getProfile().equals(android.os.Process.myUserHandle())) {
+ return -1;
+ } else if (bInfo.getProfile().equals(android.os.Process.myUserHandle())) {
+ return 1;
+ }
+ }
+ return result;
+ }
+};
diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java
index e3eb76c25..dcaf1f211 100644
--- a/src/com/android/launcher3/widget/WidgetCell.java
+++ b/src/com/android/launcher3/widget/WidgetCell.java
@@ -21,17 +21,14 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.View.OnLayoutChangeListener;
-import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
@@ -41,7 +38,13 @@ import com.android.launcher3.WidgetPreviewLoader.PreviewLoadRequest;
import com.android.launcher3.compat.AppWidgetManagerCompat;
/**
- * Represents the individual cell of the widget inside the widget tray.
+ * Represents the individual cell of the widget inside the widget tray. The preview is drawn
+ * horizontally centered, and scaled down if needed.
+ *
+ * This view does not support padding. Since the image is scaled down to fit the view, padding will
+ * further decrease the scaling factor. Drag-n-drop uses the view bounds for showing a smooth
+ * transition from the view to drag view, so when adding padding support, DnD would need to
+ * consider the appropriate scaling factor.
*/
public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
@@ -59,13 +62,11 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
private int mPresetPreviewSize;
int cellSize;
- private ImageView mWidgetImage;
+ private WidgetImageView mWidgetImage;
private TextView mWidgetName;
private TextView mWidgetDims;
- private final Rect mOrigImgPadding = new Rect();
private String mDimensionsFormatString;
- private boolean mIsAppWidget;
private Object mInfo;
private WidgetPreviewLoader mWidgetPreviewLoader;
@@ -101,12 +102,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
protected void onFinishInflate() {
super.onFinishInflate();
- mWidgetImage = (ImageView) findViewById(R.id.widget_preview);
- mOrigImgPadding.left = mWidgetImage.getPaddingLeft();
- mOrigImgPadding.top = mWidgetImage.getPaddingTop();
- mOrigImgPadding.right = mWidgetImage.getPaddingRight();
- mOrigImgPadding.bottom = mWidgetImage.getPaddingBottom();
-
+ mWidgetImage = (WidgetImageView) findViewById(R.id.widget_preview);
mWidgetName = ((TextView) findViewById(R.id.widget_name));
mWidgetDims = ((TextView) findViewById(R.id.widget_dims));
}
@@ -119,7 +115,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
Log.d(TAG, "reset called on:" + mWidgetName.getText());
}
mWidgetImage.animate().cancel();
- mWidgetImage.setImageDrawable(null);
+ mWidgetImage.setBitmap(null);
mWidgetName.setText(null);
mWidgetDims.setText(null);
@@ -133,15 +129,11 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
* Apply the widget provider info to the view.
*/
public void applyFromAppWidgetProviderInfo(LauncherAppWidgetProviderInfo info,
- int maxWidth, WidgetPreviewLoader loader) {
+ WidgetPreviewLoader loader) {
LauncherAppState app = LauncherAppState.getInstance();
DeviceProfile grid = app.getDynamicGrid().getDeviceProfile();
- mIsAppWidget = true;
mInfo = info;
- if (maxWidth > -1) {
- mWidgetImage.setMaxWidth(maxWidth);
- }
// TODO(hyunyoungs): setup a cache for these labels.
mWidgetName.setText(AppWidgetManagerCompat.getInstance(getContext()).loadLabel(info));
int hSpan = Math.min(info.spanX, grid.numColumns);
@@ -155,7 +147,6 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
*/
public void applyFromResolveInfo(
PackageManager pm, ResolveInfo info, WidgetPreviewLoader loader) {
- mIsAppWidget = false;
mInfo = info;
CharSequence label = info.loadLabel(pm);
mWidgetName.setText(label);
@@ -172,20 +163,8 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
}
public void applyPreview(Bitmap bitmap) {
- FastBitmapDrawable preview = new FastBitmapDrawable(bitmap);
-
- if (preview != null) {
- mWidgetImage.setImageDrawable(preview);
-
- if (mIsAppWidget) {
- // center horizontally
- int[] imageSize = getPreviewSize();
- int centerAmount = (imageSize[0] - preview.getIntrinsicWidth()) / 2;
- mWidgetImage.setPadding(mOrigImgPadding.left + centerAmount,
- mOrigImgPadding.top,
- mOrigImgPadding.right,
- mOrigImgPadding.bottom);
- }
+ if (bitmap != null) {
+ mWidgetImage.setBitmap(bitmap);
mWidgetImage.setAlpha(0f);
mWidgetImage.animate().alpha(1.0f).setDuration(FADE_IN_DURATION_MS);
}
diff --git a/src/com/android/launcher3/widget/WidgetImageView.java b/src/com/android/launcher3/widget/WidgetImageView.java
index f1eaf6488..6f8fd897b 100644
--- a/src/com/android/launcher3/widget/WidgetImageView.java
+++ b/src/com/android/launcher3/widget/WidgetImageView.java
@@ -17,25 +17,73 @@
package com.android.launcher3.widget;
import android.content.Context;
+import android.graphics.Bitmap;
import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.util.AttributeSet;
-import android.widget.ImageView;
+import android.view.View;
-public class WidgetImageView extends ImageView {
+/**
+ * View that draws a bitmap horizontally centered. If the image width is greater than the view
+ * width, the image is scaled down appropriately.
+ */
+public class WidgetImageView extends View {
+
+ private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
+ private final RectF mDstRectF = new RectF();
+ private Bitmap mBitmap;
+
+ public WidgetImageView(Context context) {
+ super(context);
+ }
public WidgetImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
+ public WidgetImageView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public void setBitmap(Bitmap bitmap) {
+ mBitmap = bitmap;
+ invalidate();
+ }
+
+ public Bitmap getBitmap() {
+ return mBitmap;
+ }
+
@Override
protected void onDraw(Canvas canvas) {
- canvas.save();
- canvas.clipRect(getScrollX() + getPaddingLeft(),
- getScrollY() + getPaddingTop(),
- getScrollX() + getRight() - getLeft() - getPaddingRight(),
- getScrollY() + getBottom() - getTop() - getPaddingBottom());
-
- super.onDraw(canvas);
- canvas.restore();
+ if (mBitmap != null) {
+ updateDstRectF();
+ canvas.drawBitmap(mBitmap, null, mDstRectF, mPaint);
+ }
+ }
+
+ private void updateDstRectF() {
+ if (mBitmap.getWidth() > getWidth()) {
+ float scale = ((float) getWidth()) / mBitmap.getWidth();
+ mDstRectF.set(0, 0, getWidth(), scale * mBitmap.getHeight());
+ } else {
+ mDstRectF.set(
+ (getWidth() - mBitmap.getWidth()) * 0.5f,
+ 0,
+ (getWidth() + mBitmap.getWidth()) * 0.5f,
+ mBitmap.getHeight());
+ }
+ }
+
+ /**
+ * @return the bounds where the image was drawn.
+ */
+ public Rect getBitmapBounds() {
+ updateDstRectF();
+ Rect rect = new Rect();
+ mDstRectF.round(rect);
+ return rect;
}
}
diff --git a/src/com/android/launcher3/widget/WidgetsContainerView.java b/src/com/android/launcher3/widget/WidgetsContainerView.java
index 00fb225ec..181c08a40 100644
--- a/src/com/android/launcher3/widget/WidgetsContainerView.java
+++ b/src/com/android/launcher3/widget/WidgetsContainerView.java
@@ -19,7 +19,6 @@ package com.android.launcher3.widget;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
-import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.LinearLayoutManager;
@@ -28,8 +27,8 @@ import android.support.v7.widget.RecyclerView.State;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
-import android.widget.ImageView;
import android.widget.Toast;
+
import com.android.launcher3.BaseContainerView;
import com.android.launcher3.CellLayout;
import com.android.launcher3.DeleteDropTarget;
@@ -37,10 +36,8 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DragController;
import com.android.launcher3.DragSource;
import com.android.launcher3.DropTarget.DragObject;
-import com.android.launcher3.FastBitmapDrawable;
import com.android.launcher3.Folder;
import com.android.launcher3.IconCache;
-import com.android.launcher3.Insettable;
import com.android.launcher3.ItemInfo;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
@@ -222,20 +219,19 @@ public class WidgetsContainerView extends BaseContainerView
private boolean beginDraggingWidget(WidgetCell v) {
// Get the widget preview as the drag representation
- ImageView image = (ImageView) v.findViewById(R.id.widget_preview);
+ WidgetImageView image = (WidgetImageView) v.findViewById(R.id.widget_preview);
PendingAddItemInfo createItemInfo = (PendingAddItemInfo) v.getTag();
// If the ImageView doesn't have a drawable yet, the widget preview hasn't been loaded and
// we abort the drag.
- if (image.getDrawable() == null) {
+ if (image.getBitmap() == null) {
return false;
}
// Compose the drag image
Bitmap preview;
- Bitmap outline;
float scale = 1f;
- Point previewPadding = null;
+ final Rect bounds = image.getBitmapBounds();
if (createItemInfo instanceof PendingAddWidgetInfo) {
// This can happen in some weird cases involving multi-touch. We can't start dragging
@@ -244,25 +240,25 @@ public class WidgetsContainerView extends BaseContainerView
PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) createItemInfo;
int[] size = mLauncher.getWorkspace().estimateItemSize(createWidgetInfo, true);
- FastBitmapDrawable previewDrawable = (FastBitmapDrawable) image.getDrawable();
+ Bitmap icon = image.getBitmap();
float minScale = 1.25f;
- int maxWidth = Math.min((int) (previewDrawable.getIntrinsicWidth() * minScale), size[0]);
+ int maxWidth = Math.min((int) (icon.getWidth() * minScale), size[0]);
int[] previewSizeBeforeScale = new int[1];
preview = getWidgetPreviewLoader().generateWidgetPreview(createWidgetInfo.info,
maxWidth, null, previewSizeBeforeScale);
- // Compare the size of the drag preview to the preview in the AppsCustomize tray
- int previewWidthInAppsCustomize = Math.min(previewSizeBeforeScale[0],
- v.getActualItemWidth());
- scale = previewWidthInAppsCustomize / (float) preview.getWidth();
-
- // The bitmap in the AppsCustomize tray is always the the same size, so there
- // might be extra pixels around the preview itself - this accounts for that
- if (previewWidthInAppsCustomize < previewDrawable.getIntrinsicWidth()) {
- int padding =
- (previewDrawable.getIntrinsicWidth() - previewWidthInAppsCustomize) / 2;
- previewPadding = new Point(padding, 0);
+
+ if (previewSizeBeforeScale[0] < icon.getWidth()) {
+ // The icon has extra padding around it.
+ int padding = (icon.getWidth() - previewSizeBeforeScale[0]) / 2;
+ if (icon.getWidth() > image.getWidth()) {
+ padding = padding * image.getWidth() / icon.getWidth();
+ }
+
+ bounds.left += padding;
+ bounds.right -= padding;
}
+ scale = bounds.width() / (float) preview.getWidth();
} else {
PendingAddShortcutInfo createShortcutInfo = (PendingAddShortcutInfo) v.getTag();
Drawable icon = mIconCache.getFullResIcon(createShortcutInfo.activityInfo);
@@ -274,16 +270,12 @@ public class WidgetsContainerView extends BaseContainerView
boolean clipAlpha = !(createItemInfo instanceof PendingAddWidgetInfo &&
(((PendingAddWidgetInfo) createItemInfo).previewImage == 0));
- // Save the preview for the outline generation, then dim the preview
- outline = Bitmap.createScaledBitmap(preview, preview.getWidth(), preview.getHeight(),
- false);
-
// Start the drag
mLauncher.lockScreenOrientation();
- mLauncher.getWorkspace().onDragStartedWithItem(createItemInfo, outline, clipAlpha);
+ mLauncher.getWorkspace().onDragStartedWithItem(createItemInfo, preview, clipAlpha);
mDragController.startDrag(image, preview, this, createItemInfo,
- DragController.DRAG_ACTION_COPY, previewPadding, scale);
- outline.recycle();
+ bounds, DragController.DRAG_ACTION_COPY, scale);
+
preview.recycle();
return true;
}
diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java
index 397d17799..2f733dcbc 100644
--- a/src/com/android/launcher3/widget/WidgetsListAdapter.java
+++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java
@@ -18,9 +18,9 @@ package com.android.launcher3.widget;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.os.Build;
import android.support.v7.widget.RecyclerView;
-import android.content.res.Resources;
import android.support.v7.widget.RecyclerView.Adapter;
import android.util.Log;
import android.view.LayoutInflater;
@@ -29,15 +29,16 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.LinearLayout;
+
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DynamicGrid;
-import com.android.launcher3.IconCache;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
import com.android.launcher3.R;
import com.android.launcher3.WidgetPreviewLoader;
+
import java.util.List;
/**
@@ -56,7 +57,6 @@ public class WidgetsListAdapter extends Adapter<WidgetsRowViewHolder> {
private Context mContext;
private Launcher mLauncher;
private LayoutInflater mLayoutInflater;
- private IconCache mIconCache;
private WidgetsModel mWidgetsModel;
private WidgetPreviewLoader mWidgetPreviewLoader;
@@ -76,9 +76,7 @@ public class WidgetsListAdapter extends Adapter<WidgetsRowViewHolder> {
mIconClickListener = iconClickListener;
mIconLongClickListener = iconLongClickListener;
-
mLauncher = launcher;
- mIconCache = LauncherAppState.getInstance().getIconCache();
setContainerHeight();
}
@@ -143,7 +141,7 @@ public class WidgetsListAdapter extends Adapter<WidgetsRowViewHolder> {
LauncherAppWidgetProviderInfo info = (LauncherAppWidgetProviderInfo) infoList.get(i);
PendingAddWidgetInfo pawi = new PendingAddWidgetInfo(info, null);
widget.setTag(pawi);
- widget.applyFromAppWidgetProviderInfo(info, -1, mWidgetPreviewLoader);
+ widget.applyFromAppWidgetProviderInfo(info, mWidgetPreviewLoader);
} else if (infoList.get(i) instanceof ResolveInfo) {
ResolveInfo info = (ResolveInfo) infoList.get(i);
PendingAddShortcutInfo pasi = new PendingAddShortcutInfo(info.activityInfo);
diff --git a/src/com/android/launcher3/widget/WidgetsModel.java b/src/com/android/launcher3/widget/WidgetsModel.java
index 71a7b9446..5a920e8d4 100644
--- a/src/com/android/launcher3/widget/WidgetsModel.java
+++ b/src/com/android/launcher3/widget/WidgetsModel.java
@@ -10,8 +10,9 @@ import android.util.Log;
import com.android.launcher3.IconCache;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherAppWidgetProviderInfo;
-import com.android.launcher3.LauncherModel.WidgetAndShortcutNameComparator;
import com.android.launcher3.compat.UserHandleCompat;
+import com.android.launcher3.model.AppNameComparator;
+import com.android.launcher3.model.WidgetsAndShortcutNameComparator;
import java.util.ArrayList;
import java.util.Collections;
@@ -40,12 +41,14 @@ public class WidgetsModel {
private RecyclerView.Adapter mAdapter;
private Comparator mWidgetAndShortcutNameComparator;
+ private Comparator mAppNameComparator;
private IconCache mIconCache;
public WidgetsModel(Context context, RecyclerView.Adapter adapter) {
mAdapter = adapter;
- mWidgetAndShortcutNameComparator = new WidgetAndShortcutNameComparator(context);
+ mWidgetAndShortcutNameComparator = new WidgetsAndShortcutNameComparator(context);
+ mAppNameComparator = (new AppNameComparator(context)).getAppInfoComparator();
mIconCache = LauncherAppState.getInstance().getIconCache();
}
@@ -108,7 +111,7 @@ public class WidgetsModel {
}
// sort.
- sortPackageItemInfos();
+ Collections.sort(mPackageItemInfos, mAppNameComparator);
for (PackageItemInfo p: mPackageItemInfos) {
Collections.sort(mWidgetsList.get(p), mWidgetAndShortcutNameComparator);
}
@@ -116,13 +119,4 @@ public class WidgetsModel {
// notify.
mAdapter.notifyDataSetChanged();
}
-
- private void sortPackageItemInfos() {
- Collections.sort(mPackageItemInfos, new Comparator<PackageItemInfo>() {
- @Override
- public int compare(PackageItemInfo lhs, PackageItemInfo rhs) {
- return lhs.title.toString().compareTo(rhs.title.toString());
- }
- });
- }
} \ No newline at end of file