diff options
63 files changed, 430 insertions, 274 deletions
diff --git a/res/drawable-hdpi/ic_widget_resize_handle.png b/res/drawable-hdpi/ic_widget_resize_handle.png Binary files differnew file mode 100644 index 000000000..844f3cf09 --- /dev/null +++ b/res/drawable-hdpi/ic_widget_resize_handle.png diff --git a/res/drawable-hdpi/widget_resize_frame.9.png b/res/drawable-hdpi/widget_resize_frame.9.png Binary files differnew file mode 100644 index 000000000..5772672b1 --- /dev/null +++ b/res/drawable-hdpi/widget_resize_frame.9.png diff --git a/res/drawable-hdpi/widget_resize_frame_holo.9.png b/res/drawable-hdpi/widget_resize_frame_holo.9.png Binary files differdeleted file mode 100644 index 2d6fcf51f..000000000 --- a/res/drawable-hdpi/widget_resize_frame_holo.9.png +++ /dev/null diff --git a/res/drawable-hdpi/widget_resize_handle_bottom.png b/res/drawable-hdpi/widget_resize_handle_bottom.png Binary files differdeleted file mode 100644 index f0afd6172..000000000 --- a/res/drawable-hdpi/widget_resize_handle_bottom.png +++ /dev/null diff --git a/res/drawable-hdpi/widget_resize_handle_left.png b/res/drawable-hdpi/widget_resize_handle_left.png Binary files differdeleted file mode 100644 index 47613b29f..000000000 --- a/res/drawable-hdpi/widget_resize_handle_left.png +++ /dev/null diff --git a/res/drawable-hdpi/widget_resize_handle_right.png b/res/drawable-hdpi/widget_resize_handle_right.png Binary files differdeleted file mode 100644 index acc28be83..000000000 --- a/res/drawable-hdpi/widget_resize_handle_right.png +++ /dev/null diff --git a/res/drawable-hdpi/widget_resize_handle_top.png b/res/drawable-hdpi/widget_resize_handle_top.png Binary files differdeleted file mode 100644 index 2c60be00c..000000000 --- a/res/drawable-hdpi/widget_resize_handle_top.png +++ /dev/null diff --git a/res/drawable-hdpi/widget_resize_shadow.9.png b/res/drawable-hdpi/widget_resize_shadow.9.png Binary files differnew file mode 100644 index 000000000..a67da6e04 --- /dev/null +++ b/res/drawable-hdpi/widget_resize_shadow.9.png diff --git a/res/drawable-mdpi/ic_widget_resize_handle.png b/res/drawable-mdpi/ic_widget_resize_handle.png Binary files differnew file mode 100644 index 000000000..c3b287ff0 --- /dev/null +++ b/res/drawable-mdpi/ic_widget_resize_handle.png diff --git a/res/drawable-mdpi/widget_resize_frame.9.png b/res/drawable-mdpi/widget_resize_frame.9.png Binary files differnew file mode 100644 index 000000000..8bc8a5c12 --- /dev/null +++ b/res/drawable-mdpi/widget_resize_frame.9.png diff --git a/res/drawable-mdpi/widget_resize_frame_holo.9.png b/res/drawable-mdpi/widget_resize_frame_holo.9.png Binary files differdeleted file mode 100644 index 028bd6248..000000000 --- a/res/drawable-mdpi/widget_resize_frame_holo.9.png +++ /dev/null diff --git a/res/drawable-mdpi/widget_resize_handle_bottom.png b/res/drawable-mdpi/widget_resize_handle_bottom.png Binary files differdeleted file mode 100644 index c838bf405..000000000 --- a/res/drawable-mdpi/widget_resize_handle_bottom.png +++ /dev/null diff --git a/res/drawable-mdpi/widget_resize_handle_left.png b/res/drawable-mdpi/widget_resize_handle_left.png Binary files differdeleted file mode 100644 index ff0b0d357..000000000 --- a/res/drawable-mdpi/widget_resize_handle_left.png +++ /dev/null diff --git a/res/drawable-mdpi/widget_resize_handle_right.png b/res/drawable-mdpi/widget_resize_handle_right.png Binary files differdeleted file mode 100644 index fc4808e3a..000000000 --- a/res/drawable-mdpi/widget_resize_handle_right.png +++ /dev/null diff --git a/res/drawable-mdpi/widget_resize_handle_top.png b/res/drawable-mdpi/widget_resize_handle_top.png Binary files differdeleted file mode 100644 index 3b1df0170..000000000 --- a/res/drawable-mdpi/widget_resize_handle_top.png +++ /dev/null diff --git a/res/drawable-mdpi/widget_resize_shadow.9.png b/res/drawable-mdpi/widget_resize_shadow.9.png Binary files differnew file mode 100644 index 000000000..2bae2b603 --- /dev/null +++ b/res/drawable-mdpi/widget_resize_shadow.9.png diff --git a/res/drawable-xhdpi/ic_widget_resize_handle.png b/res/drawable-xhdpi/ic_widget_resize_handle.png Binary files differnew file mode 100644 index 000000000..f445a1c08 --- /dev/null +++ b/res/drawable-xhdpi/ic_widget_resize_handle.png diff --git a/res/drawable-xhdpi/widget_resize_frame.9.png b/res/drawable-xhdpi/widget_resize_frame.9.png Binary files differnew file mode 100644 index 000000000..e6cf0afde --- /dev/null +++ b/res/drawable-xhdpi/widget_resize_frame.9.png diff --git a/res/drawable-xhdpi/widget_resize_frame_holo.9.png b/res/drawable-xhdpi/widget_resize_frame_holo.9.png Binary files differdeleted file mode 100644 index 76cec606d..000000000 --- a/res/drawable-xhdpi/widget_resize_frame_holo.9.png +++ /dev/null diff --git a/res/drawable-xhdpi/widget_resize_handle_bottom.png b/res/drawable-xhdpi/widget_resize_handle_bottom.png Binary files differdeleted file mode 100644 index 19437d7dc..000000000 --- a/res/drawable-xhdpi/widget_resize_handle_bottom.png +++ /dev/null diff --git a/res/drawable-xhdpi/widget_resize_handle_left.png b/res/drawable-xhdpi/widget_resize_handle_left.png Binary files differdeleted file mode 100644 index 28c5487ec..000000000 --- a/res/drawable-xhdpi/widget_resize_handle_left.png +++ /dev/null diff --git a/res/drawable-xhdpi/widget_resize_handle_right.png b/res/drawable-xhdpi/widget_resize_handle_right.png Binary files differdeleted file mode 100644 index 4f672a602..000000000 --- a/res/drawable-xhdpi/widget_resize_handle_right.png +++ /dev/null diff --git a/res/drawable-xhdpi/widget_resize_handle_top.png b/res/drawable-xhdpi/widget_resize_handle_top.png Binary files differdeleted file mode 100644 index e866c008c..000000000 --- a/res/drawable-xhdpi/widget_resize_handle_top.png +++ /dev/null diff --git a/res/drawable-xhdpi/widget_resize_shadow.9.png b/res/drawable-xhdpi/widget_resize_shadow.9.png Binary files differnew file mode 100644 index 000000000..99e9e78cd --- /dev/null +++ b/res/drawable-xhdpi/widget_resize_shadow.9.png diff --git a/res/drawable-xxhdpi/ic_widget_resize_handle.png b/res/drawable-xxhdpi/ic_widget_resize_handle.png Binary files differnew file mode 100644 index 000000000..144cac996 --- /dev/null +++ b/res/drawable-xxhdpi/ic_widget_resize_handle.png diff --git a/res/drawable-xxhdpi/widget_resize_frame.9.png b/res/drawable-xxhdpi/widget_resize_frame.9.png Binary files differnew file mode 100644 index 000000000..7a49d01da --- /dev/null +++ b/res/drawable-xxhdpi/widget_resize_frame.9.png diff --git a/res/drawable-xxhdpi/widget_resize_frame_holo.9.png b/res/drawable-xxhdpi/widget_resize_frame_holo.9.png Binary files differdeleted file mode 100644 index 1681387a1..000000000 --- a/res/drawable-xxhdpi/widget_resize_frame_holo.9.png +++ /dev/null diff --git a/res/drawable-xxhdpi/widget_resize_handle_bottom.png b/res/drawable-xxhdpi/widget_resize_handle_bottom.png Binary files differdeleted file mode 100644 index d549fcd91..000000000 --- a/res/drawable-xxhdpi/widget_resize_handle_bottom.png +++ /dev/null diff --git a/res/drawable-xxhdpi/widget_resize_handle_left.png b/res/drawable-xxhdpi/widget_resize_handle_left.png Binary files differdeleted file mode 100644 index dd56dad15..000000000 --- a/res/drawable-xxhdpi/widget_resize_handle_left.png +++ /dev/null diff --git a/res/drawable-xxhdpi/widget_resize_handle_right.png b/res/drawable-xxhdpi/widget_resize_handle_right.png Binary files differdeleted file mode 100644 index 296a1c166..000000000 --- a/res/drawable-xxhdpi/widget_resize_handle_right.png +++ /dev/null diff --git a/res/drawable-xxhdpi/widget_resize_handle_top.png b/res/drawable-xxhdpi/widget_resize_handle_top.png Binary files differdeleted file mode 100644 index e86270ad1..000000000 --- a/res/drawable-xxhdpi/widget_resize_handle_top.png +++ /dev/null diff --git a/res/drawable-xxhdpi/widget_resize_shadow.9.png b/res/drawable-xxhdpi/widget_resize_shadow.9.png Binary files differnew file mode 100644 index 000000000..ae0f564dd --- /dev/null +++ b/res/drawable-xxhdpi/widget_resize_shadow.9.png diff --git a/res/drawable-xxxhdpi/ic_widget_resize_handle.png b/res/drawable-xxxhdpi/ic_widget_resize_handle.png Binary files differnew file mode 100644 index 000000000..4bde6b9a6 --- /dev/null +++ b/res/drawable-xxxhdpi/ic_widget_resize_handle.png diff --git a/res/drawable-xxxhdpi/widget_resize_frame.9.png b/res/drawable-xxxhdpi/widget_resize_frame.9.png Binary files differnew file mode 100644 index 000000000..9b711f2c5 --- /dev/null +++ b/res/drawable-xxxhdpi/widget_resize_frame.9.png diff --git a/res/drawable-xxxhdpi/widget_resize_shadow.9.png b/res/drawable-xxxhdpi/widget_resize_shadow.9.png Binary files differnew file mode 100644 index 000000000..defb311ca --- /dev/null +++ b/res/drawable-xxxhdpi/widget_resize_shadow.9.png 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/values/dimens.xml b/res/values/dimens.xml index d2f6237a8..60591e14a 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -28,7 +28,10 @@ <dimen name="dynamic_grid_overview_bar_item_width">80dp</dimen> <dimen name="dynamic_grid_overview_bar_spacer_width">20dp</dimen> +<!-- App Widget resize frame --> <dimen name="default_widget_padding">8dp</dimen> + <dimen name="widget_handle_margin">13dp</dimen> + <dimen name="resize_frame_background_padding">24dp</dimen> <!-- Cling --> <dimen name="cling_migration_logo_height">240dp</dimen> diff --git a/res/values/strings.xml b/res/values/strings.xml index 51ad51f12..18f97c84d 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] --> - <string name="action_move_here">Move here</string> + <!-- Accessibility action to move item to the current location. [CHAR_LIMIT=30] --> + <string name="action_move_here">Move item 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/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/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java index 3c698c014..e6bf52531 100644 --- a/src/com/android/launcher3/AppWidgetResizeFrame.java +++ b/src/com/android/launcher3/AppWidgetResizeFrame.java @@ -15,24 +15,36 @@ import android.widget.FrameLayout; import android.widget.ImageView; public class AppWidgetResizeFrame extends FrameLayout { - private LauncherAppWidgetHostView mWidgetView; - private CellLayout mCellLayout; - private DragLayer mDragLayer; - private ImageView mLeftHandle; - private ImageView mRightHandle; - private ImageView mTopHandle; - private ImageView mBottomHandle; + private static final int SNAP_DURATION = 150; + private static final float DIMMED_HANDLE_ALPHA = 0f; + private static final float RESIZE_THRESHOLD = 0.66f; + + private static Rect sTmpRect = new Rect(); + + private final Launcher mLauncher; + private final LauncherAppWidgetHostView mWidgetView; + private final CellLayout mCellLayout; + private final DragLayer mDragLayer; + + private final ImageView mLeftHandle; + private final ImageView mRightHandle; + private final ImageView mTopHandle; + private final ImageView mBottomHandle; + + private final Rect mWidgetPadding; + + private final int mBackgroundPadding; + private final int mTouchTargetWidth; + + private final int[] mDirectionVector = new int[2]; + private final int[] mLastDirectionVector = new int[2]; + private final int[] mTmpPt = new int[2]; private boolean mLeftBorderActive; private boolean mRightBorderActive; private boolean mTopBorderActive; private boolean mBottomBorderActive; - private int mWidgetPaddingLeft; - private int mWidgetPaddingRight; - private int mWidgetPaddingTop; - private int mWidgetPaddingBottom; - private int mBaselineWidth; private int mBaselineHeight; private int mBaselineX; @@ -48,30 +60,9 @@ public class AppWidgetResizeFrame extends FrameLayout { private int mDeltaXAddOn; private int mDeltaYAddOn; - private int mBackgroundPadding; - private int mTouchTargetWidth; - private int mTopTouchRegionAdjustment = 0; private int mBottomTouchRegionAdjustment = 0; - int[] mDirectionVector = new int[2]; - int[] mLastDirectionVector = new int[2]; - int[] mTmpPt = new int[2]; - - final int SNAP_DURATION = 150; - final int BACKGROUND_PADDING = 24; - final float DIMMED_HANDLE_ALPHA = 0f; - final float RESIZE_THRESHOLD = 0.66f; - - private static Rect mTmpRect = new Rect(); - - public static final int LEFT = 0; - public static final int TOP = 1; - public static final int RIGHT = 2; - public static final int BOTTOM = 3; - - private Launcher mLauncher; - public AppWidgetResizeFrame(Context context, LauncherAppWidgetHostView widgetView, CellLayout cellLayout, DragLayer dragLayer) { @@ -87,49 +78,49 @@ public class AppWidgetResizeFrame extends FrameLayout { mMinHSpan = info.minSpanX; mMinVSpan = info.minSpanY; - setBackgroundResource(R.drawable.widget_resize_frame_holo); + setBackgroundResource(R.drawable.widget_resize_shadow); + setForeground(getResources().getDrawable(R.drawable.widget_resize_frame)); setPadding(0, 0, 0, 0); + final int handleMargin = getResources().getDimensionPixelSize(R.dimen.widget_handle_margin); LayoutParams lp; mLeftHandle = new ImageView(context); - mLeftHandle.setImageResource(R.drawable.widget_resize_handle_left); - lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, + mLeftHandle.setImageResource(R.drawable.ic_widget_resize_handle); + lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.LEFT | Gravity.CENTER_VERTICAL); + lp.leftMargin = handleMargin; addView(mLeftHandle, lp); mRightHandle = new ImageView(context); - mRightHandle.setImageResource(R.drawable.widget_resize_handle_right); - lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, + mRightHandle.setImageResource(R.drawable.ic_widget_resize_handle); + lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.RIGHT | Gravity.CENTER_VERTICAL); + lp.rightMargin = handleMargin; addView(mRightHandle, lp); mTopHandle = new ImageView(context); - mTopHandle.setImageResource(R.drawable.widget_resize_handle_top); - lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, + mTopHandle.setImageResource(R.drawable.ic_widget_resize_handle); + lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.TOP); + lp.topMargin = handleMargin; addView(mTopHandle, lp); mBottomHandle = new ImageView(context); - mBottomHandle.setImageResource(R.drawable.widget_resize_handle_bottom); - lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, + mBottomHandle.setImageResource(R.drawable.ic_widget_resize_handle); + lp = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM); + lp.bottomMargin = handleMargin; addView(mBottomHandle, lp); - Rect p = new Rect(0, 0, 0, 0); if (!info.isCustomWidget) { - p = AppWidgetHostView.getDefaultPaddingForWidget(context, + mWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(context, widgetView.getAppWidgetInfo().provider, null); } else { Resources r = context.getResources(); int padding = r.getDimensionPixelSize(R.dimen.default_widget_padding); - p.set(padding, padding, padding, padding); + mWidgetPadding = new Rect(padding, padding, padding, padding); } - mWidgetPaddingLeft = p.left; - mWidgetPaddingTop = p.top; - mWidgetPaddingRight = p.right; - mWidgetPaddingBottom = p.bottom; - if (mResizeMode == AppWidgetProviderInfo.RESIZE_HORIZONTAL) { mTopHandle.setVisibility(GONE); mBottomHandle.setVisibility(GONE); @@ -138,8 +129,8 @@ public class AppWidgetResizeFrame extends FrameLayout { mRightHandle.setVisibility(GONE); } - final float density = mLauncher.getResources().getDisplayMetrics().density; - mBackgroundPadding = (int) Math.ceil(density * BACKGROUND_PADDING); + mBackgroundPadding = getResources() + .getDimensionPixelSize(R.dimen.resize_frame_background_padding); mTouchTargetWidth = 2 * mBackgroundPadding; // When we create the resize frame, we first mark all cells as unoccupied. The appropriate @@ -344,9 +335,9 @@ public class AppWidgetResizeFrame extends FrameLayout { static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Launcher launcher, int spanX, int spanY) { - getWidgetSizeRanges(launcher, spanX, spanY, mTmpRect); - widgetView.updateAppWidgetSize(null, mTmpRect.left, mTmpRect.top, - mTmpRect.right, mTmpRect.bottom); + getWidgetSizeRanges(launcher, spanX, spanY, sTmpRect); + widgetView.updateAppWidgetSize(null, sTmpRect.left, sTmpRect.top, + sTmpRect.right, sTmpRect.bottom); } public static Rect getWidgetSizeRanges(Launcher launcher, int spanX, int spanY, Rect rect) { @@ -404,19 +395,19 @@ public class AppWidgetResizeFrame extends FrameLayout { public void snapToWidget(boolean animate) { final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams(); - int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding - mWidgetPaddingLeft - - mWidgetPaddingRight; - int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding - mWidgetPaddingTop - - mWidgetPaddingBottom; + int newWidth = mWidgetView.getWidth() + 2 * mBackgroundPadding + - mWidgetPadding.left - mWidgetPadding.right; + int newHeight = mWidgetView.getHeight() + 2 * mBackgroundPadding + - mWidgetPadding.top - mWidgetPadding.bottom; mTmpPt[0] = mWidgetView.getLeft(); mTmpPt[1] = mWidgetView.getTop(); mDragLayer.getDescendantCoordRelativeToSelf(mCellLayout.getShortcutsAndWidgets(), mTmpPt); - int newX = mTmpPt[0] - mBackgroundPadding + mWidgetPaddingLeft; - int newY = mTmpPt[1] - mBackgroundPadding + mWidgetPaddingTop; + int newX = mTmpPt[0] - mBackgroundPadding + mWidgetPadding.left; + int newY = mTmpPt[1] - mBackgroundPadding + mWidgetPadding.top; - // We need to make sure the frame's touchable regions lie fully within the bounds of the + // We need to make sure the frame's touchable regions lie fully within the bounds of the // DragLayer. We allow the actual handles to be clipped, but we shift the touch regions // down accordingly to provide a proper touch target. if (newY < 0) { 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/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..edcdc1149 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(); @@ -3010,7 +3012,7 @@ public class CellLayout extends ViewGroup { // 2. When long clicking on an empty cell in a CellLayout, we save information about the // cellX and cellY coordinates and which page was clicked. We then set this as a tag on // the CellLayout that was long clicked - static final class CellInfo { + public static final class CellInfo { View cell; int cellX = -1; int cellY = -1; @@ -3019,7 +3021,7 @@ public class CellLayout extends ViewGroup { long screenId; long container; - CellInfo(View v, ItemInfo info) { + public CellInfo(View v, ItemInfo info) { cell = v; cellX = info.cellX; cellY = info.cellY; diff --git a/src/com/android/launcher3/DragLayer.java b/src/com/android/launcher3/DragLayer.java index e25e6152c..423a9a3d5 100644 --- a/src/com/android/launcher3/DragLayer.java +++ b/src/com/android/launcher3/DragLayer.java @@ -39,6 +39,7 @@ import android.view.animation.Interpolator; import android.widget.FrameLayout; import android.widget.TextView; +import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.util.Thunk; import java.util.ArrayList; @@ -48,34 +49,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 +89,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 +917,9 @@ public class DragLayer extends InsettableFrameLayout { void showPageHints() { mShowPageHints = true; + Workspace workspace = mLauncher.getWorkspace(); + getDescendantRectRelativeToSelf(workspace.getChildAt(workspace.getChildCount() - 1), + mScrollChildPosition); invalidate(); } @@ -937,10 +943,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 +950,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/Folder.java b/src/com/android/launcher3/Folder.java index 69b18374a..d0a7ba3f8 100644 --- a/src/com/android/launcher3/Folder.java +++ b/src/com/android/launcher3/Folder.java @@ -49,13 +49,15 @@ import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputMethodManager; import android.widget.LinearLayout; import android.widget.TextView; + import com.android.launcher3.CellLayout.CellInfo; import com.android.launcher3.DragController.DragListener; import com.android.launcher3.FolderInfo.FolderListener; -import com.android.launcher3.LauncherAccessibilityDelegate.AccessibilityDragSource; import com.android.launcher3.UninstallDropTarget.UninstallSource; import com.android.launcher3.Workspace.ItemOperator; +import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource; import com.android.launcher3.util.Thunk; + import java.util.ArrayList; import java.util.Collections; @@ -352,7 +354,7 @@ public class Folder extends LinearLayout implements DragSource, View.OnClickList /** * @return the FolderInfo object associated with this folder */ - FolderInfo getInfo() { + public FolderInfo getInfo() { return mInfo; } diff --git a/src/com/android/launcher3/FolderPagedView.java b/src/com/android/launcher3/FolderPagedView.java index de30b606a..06ed58895 100644 --- a/src/com/android/launcher3/FolderPagedView.java +++ b/src/com/android/launcher3/FolderPagedView.java @@ -241,6 +241,11 @@ public class FolderPagedView extends PagedView { return page; } + @Override + protected int getChildGap() { + return getPaddingLeft() + getPaddingRight(); + } + public void setFixedSize(int width, int height) { width -= (getPaddingLeft() + getPaddingRight()); height -= (getPaddingTop() + getPaddingBottom()); 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/Launcher.java b/src/com/android/launcher3/Launcher.java index 51ba2dfc9..7b7b61795 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -96,6 +96,7 @@ import android.widget.Toast; import com.android.launcher3.DropTarget.DragObject; import com.android.launcher3.PagedView.PageSwitchListener; +import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.compat.AppWidgetManagerCompat; import com.android.launcher3.compat.LauncherActivityInfoCompat; import com.android.launcher3.compat.LauncherAppsCompat; @@ -3184,7 +3185,7 @@ public class Launcher extends Activity } } - void closeFolder(Folder folder) { + public void closeFolder(Folder folder) { folder.getInfo().opened = false; ViewGroup parent = (ViewGroup) folder.getParent().getParent(); @@ -3337,7 +3338,7 @@ public class Launcher extends Activity true); } - protected void showWorkspace(boolean animated, Runnable onCompleteRunnable) { + public void showWorkspace(boolean animated, Runnable onCompleteRunnable) { showWorkspace(WorkspaceStateTransitionAnimation.SCROLL_TO_CURRENT_PAGE, animated, onCompleteRunnable, true); } diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index bde54c335..f540eb47d 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -31,6 +31,7 @@ import android.util.Log; import android.view.Display; import android.view.WindowManager; +import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.compat.LauncherAppsCompat; import com.android.launcher3.compat.PackageInstallerCompat; import com.android.launcher3.util.Thunk; diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java index 0b3049c2e..3e05f57b9 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; @@ -793,7 +792,7 @@ public class LauncherModel extends BroadcastReceiver /** * Move an item in the DB to a new <container, screen, cellX, cellY> */ - static void moveItemInDatabase(Context context, final ItemInfo item, final long container, + public static void moveItemInDatabase(Context context, final ItemInfo item, final long container, final long screenId, final int cellX, final int cellY) { item.container = container; item.cellX = cellX; @@ -889,7 +888,7 @@ public class LauncherModel extends BroadcastReceiver /** * Update an item to the database in a specified container. */ - static void updateItemInDatabase(Context context, final ItemInfo item) { + public static void updateItemInDatabase(Context context, final ItemInfo item) { final ContentValues values = new ContentValues(); item.onAddToDatabase(context, values); updateItemInDatabaseHelper(context, values, item, "updateItemInDatabase"); @@ -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/PagedView.java b/src/com/android/launcher3/PagedView.java index 554a975e7..dda9a166c 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -407,7 +407,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc /** * Returns the index of the currently displayed page. */ - int getCurrentPage() { + public int getCurrentPage() { return mCurrentPage; } @@ -422,7 +422,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc return getChildCount(); } - View getPageAt(int index) { + public View getPageAt(int index) { return getChildAt(index); } @@ -633,9 +633,6 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc if (mCurrentPage != getNextPage()) { AccessibilityEvent ev = AccessibilityEvent.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED); - ev.setItemCount(getChildCount()); - ev.setFromIndex(getNextPage()); - ev.setToIndex(getNextPage()); sendAccessibilityEventUnchecked(ev); } @@ -912,8 +909,7 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc pageGap = getPaddingRight(); } - childLeft += childWidth + pageGap - + (lp.isFullScreenPage ? 0 : (getPaddingLeft() + getPaddingRight())); + childLeft += childWidth + pageGap + getChildGap(); } } @@ -961,6 +957,10 @@ public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarc } } + protected int getChildGap() { + return 0; + } + private void updateMaxScrollX() { int childCount = getChildCount(); if (childCount > 0) { diff --git a/src/com/android/launcher3/SmoothPagedView.java b/src/com/android/launcher3/SmoothPagedView.java index 4e331aa2c..0f9b23cda 100644 --- a/src/com/android/launcher3/SmoothPagedView.java +++ b/src/com/android/launcher3/SmoothPagedView.java @@ -152,7 +152,7 @@ public abstract class SmoothPagedView extends PagedView { } @Override - protected void snapToPage(int whichPage) { + public void snapToPage(int whichPage) { if (mScrollMode == X_LARGE_MODE) { super.snapToPage(whichPage); } else { diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 58e5877a6..8c1c7d689 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -57,19 +57,22 @@ import android.view.accessibility.AccessibilityManager; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import android.widget.TextView; + import com.android.launcher3.FolderIcon.FolderRingAnimator; import com.android.launcher3.Launcher.CustomContentCallbacks; import com.android.launcher3.Launcher.LauncherOverlay; -import com.android.launcher3.LauncherAccessibilityDelegate.AccessibilityDragSource; import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.UninstallDropTarget.UninstallSource; +import com.android.launcher3.accessibility.LauncherAccessibilityDelegate; import com.android.launcher3.accessibility.OverviewScreenAccessibilityDelegate; +import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.AccessibilityDragSource; import com.android.launcher3.compat.UserHandleCompat; import com.android.launcher3.util.LongArrayMap; import com.android.launcher3.util.Thunk; import com.android.launcher3.util.WallpaperUtils; import com.android.launcher3.widget.PendingAddShortcutInfo; import com.android.launcher3.widget.PendingAddWidgetInfo; + import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -494,7 +497,7 @@ public class Workspace extends SmoothPagedView /** * @return The open folder on the current screen, or null if there is none */ - Folder getOpenFolder() { + public Folder getOpenFolder() { DragLayer dragLayer = mLauncher.getDragLayer(); int count = dragLayer.getChildCount(); for (int i = 0; i < count; i++) { @@ -857,7 +860,7 @@ public class Workspace extends SmoothPagedView return -1; } - ArrayList<Long> getScreenOrder() { + public ArrayList<Long> getScreenOrder() { return mScreenOrder; } diff --git a/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java index 0f1724155..78accf720 100644 --- a/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java +++ b/src/com/android/launcher3/accessibility/DragAndDropAccessibilityDelegate.java @@ -26,7 +26,6 @@ import android.view.View.OnClickListener; import android.view.accessibility.AccessibilityEvent; import com.android.launcher3.CellLayout; -import com.android.launcher3.LauncherAccessibilityDelegate; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; diff --git a/src/com/android/launcher3/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java index 3992e6390..eeec8c580 100644 --- a/src/com/android/launcher3/LauncherAccessibilityDelegate.java +++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java @@ -1,4 +1,4 @@ -package com.android.launcher3; +package com.android.launcher3.accessibility; import android.annotation.TargetApi; import android.app.AlertDialog; @@ -16,6 +16,24 @@ import android.view.View.AccessibilityDelegate; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; +import com.android.launcher3.AppInfo; +import com.android.launcher3.AppWidgetResizeFrame; +import com.android.launcher3.CellLayout; +import com.android.launcher3.DeleteDropTarget; +import com.android.launcher3.Folder; +import com.android.launcher3.FolderInfo; +import com.android.launcher3.InfoDropTarget; +import com.android.launcher3.ItemInfo; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppWidgetHostView; +import com.android.launcher3.LauncherAppWidgetInfo; +import com.android.launcher3.LauncherModel; +import com.android.launcher3.LauncherSettings; +import com.android.launcher3.PendingAddItemInfo; +import com.android.launcher3.R; +import com.android.launcher3.ShortcutInfo; +import com.android.launcher3.UninstallDropTarget; +import com.android.launcher3.Workspace; import com.android.launcher3.util.Thunk; import java.util.ArrayList; diff --git a/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java index 6f89d0eb0..80ddc13b7 100644 --- a/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java +++ b/src/com/android/launcher3/accessibility/WorkspaceAccessibilityHelper.java @@ -23,8 +23,7 @@ import com.android.launcher3.AppInfo; import com.android.launcher3.CellLayout; import com.android.launcher3.FolderInfo; import com.android.launcher3.ItemInfo; -import com.android.launcher3.LauncherAccessibilityDelegate; -import com.android.launcher3.LauncherAccessibilityDelegate.DragType; +import com.android.launcher3.accessibility.LauncherAccessibilityDelegate.DragType; import com.android.launcher3.R; import com.android.launcher3.ShortcutInfo; 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..61e895283 --- /dev/null +++ b/src/com/android/launcher3/model/WidgetsAndShortcutNameComparator.java @@ -0,0 +1,68 @@ +package com.android.launcher3.model; + +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 com.android.launcher3.compat.UserHandleCompat; + +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; + private final UserHandleCompat mMainHandle; + + public WidgetsAndShortcutNameComparator(Context context) { + mManager = AppWidgetManagerCompat.getInstance(context); + mPackageManager = context.getPackageManager(); + mLabelCache = new HashMap<Object, String>(); + mCollator = Collator.getInstance(); + mMainHandle = UserHandleCompat.myUserHandle(); + } + + @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); + } + + // Currently, there is no work profile shortcuts, hence only considering the widget cases. + + boolean aWorkProfile = (a instanceof LauncherAppWidgetProviderInfo) && + !mMainHandle.equals(mManager.getUser((LauncherAppWidgetProviderInfo) a)); + boolean bWorkProfile = (b instanceof LauncherAppWidgetProviderInfo) && + !mMainHandle.equals(mManager.getUser((LauncherAppWidgetProviderInfo) b)); + + // Independent of how the labels compare, if only one of the two widget info belongs to + // work profile, put that one in the back. + if (aWorkProfile && !bWorkProfile) { + return 1; + } + if (!aWorkProfile && bWorkProfile) { + return -1; + } + return mCollator.compare(labelA, labelB); + } +}; diff --git a/src/com/android/launcher3/widget/WidgetsListAdapter.java b/src/com/android/launcher3/widget/WidgetsListAdapter.java index 2f733dcbc..3916c00d2 100644 --- a/src/com/android/launcher3/widget/WidgetsListAdapter.java +++ b/src/com/android/launcher3/widget/WidgetsListAdapter.java @@ -183,7 +183,6 @@ public class WidgetsListAdapter extends Adapter<WidgetsRowViewHolder> { } } - @Override public boolean onFailedToRecycleView(WidgetsRowViewHolder holder) { // If child views are animating, then the RecyclerView may choose not to recycle the view, // causing extraneous onCreateViewHolder() calls. It is safe in this case to continue 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 |