Merge "Fixing potential issue where loader was still running after the fragment was detached. (Bug 5682275)"
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 81525cf..ad38b9b 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -20,12 +20,12 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="application_name" msgid="8424725141379931883">"启动器"</string>
- <string name="uid_name" msgid="3371120195364560632">"Android 核心应用程序"</string>
+ <string name="uid_name" msgid="3371120195364560632">"Android 核心应用"</string>
<string name="folder_name" msgid="8551881338202938211"></string>
<string name="chooser_wallpaper" msgid="6063168087625352235">"选择壁纸来源"</string>
<string name="wallpaper_instructions" msgid="4215640646180727542">"设置壁纸"</string>
<string name="pick_wallpaper" msgid="5630222540525626723">"壁纸"</string>
- <string name="activity_not_found" msgid="217823393239365967">"未安装该应用程序。"</string>
+ <string name="activity_not_found" msgid="217823393239365967">"未安装该应用。"</string>
<string name="widgets_tab_label" msgid="9145860100000983599">"窗口小部件"</string>
<string name="long_press_widget_to_add" msgid="7395697462851217506">"触摸并按住可选取窗口小部件。"</string>
<string name="market" msgid="2652226429823445833">"购买"</string>
@@ -36,7 +36,7 @@
<string name="rename_action" msgid="6016003384693240896">"确定"</string>
<string name="cancel_action" msgid="3811860427489435048">"取消"</string>
<string name="menu_item_add_item" msgid="6233177331075781114">"添加到主屏幕"</string>
- <string name="group_applications" msgid="2103752818818161976">"应用程序"</string>
+ <string name="group_applications" msgid="2103752818818161976">"应用"</string>
<string name="group_shortcuts" msgid="9133529424900391877">"快捷方式"</string>
<string name="group_widgets" msgid="6704978494073105844">"窗口小部件"</string>
<string name="group_wallpapers" msgid="1568191644272224858">"壁纸"</string>
@@ -46,56 +46,56 @@
<string name="shortcut_uninstalled" msgid="2129499669449749995">"已删除“<xliff:g id="NAME">%s</xliff:g>”快捷方式。"</string>
<string name="shortcut_duplicate" msgid="4757756326465060694">"“<xliff:g id="NAME">%s</xliff:g>”快捷方式已存在。"</string>
<string name="title_select_shortcut" msgid="1873670208166882222">"选择快捷方式"</string>
- <string name="title_select_application" msgid="1793455815754848652">"选择应用程序"</string>
- <string name="all_apps_button_label" msgid="2578400570124163469">"应用程序"</string>
+ <string name="title_select_application" msgid="1793455815754848652">"选择应用"</string>
+ <string name="all_apps_button_label" msgid="2578400570124163469">"应用"</string>
<string name="all_apps_home_button_label" msgid="1022222300329398558">"主屏幕"</string>
<string name="delete_zone_label_workspace" msgid="7153615831493049150">"删除"</string>
<string name="delete_zone_label_all_apps" msgid="6664588234817475108">"卸载"</string>
<string name="delete_target_label" msgid="665300185123139530">"删除"</string>
<string name="delete_target_uninstall_label" msgid="748894921183769150">"卸载"</string>
- <string name="info_target_label" msgid="4019495079517426980">"应用程序信息"</string>
+ <string name="info_target_label" msgid="4019495079517426980">"应用信息"</string>
<string name="accessibility_search_button" msgid="816822994629942611">"搜索"</string>
<string name="accessibility_voice_search_button" msgid="3938249215065842475">"语音搜索"</string>
- <string name="accessibility_all_apps_button" msgid="8803738611398979849">"应用程序"</string>
+ <string name="accessibility_all_apps_button" msgid="8803738611398979849">"应用"</string>
<string name="accessibility_delete_button" msgid="3628162007991023603">"删除"</string>
<string name="delete_zone_label_all_apps_system_app" msgid="3683920959591819044">"卸载更新"</string>
<string name="menu_add" msgid="3065046628354640854">"添加"</string>
- <string name="menu_manage_apps" msgid="2308685199463588895">"管理应用程序"</string>
+ <string name="menu_manage_apps" msgid="2308685199463588895">"管理应用"</string>
<string name="menu_wallpaper" msgid="5837429080911269832">"壁纸"</string>
<string name="menu_search" msgid="4826514464423239041">"搜索"</string>
<string name="menu_notifications" msgid="6424587053194766192">"通知"</string>
<string name="menu_settings" msgid="3946232973327980394">"系统设置"</string>
<string name="menu_help" msgid="4901160661634590633">"帮助"</string>
- <string name="cab_menu_delete_app" msgid="4089398025537640349">"卸载该应用程序"</string>
- <string name="cab_menu_app_info" msgid="914548323652698884">"应用程序详情"</string>
- <string name="cab_app_selection_text" msgid="6378522164293415735">"选中了 1 个应用程序"</string>
+ <string name="cab_menu_delete_app" msgid="4089398025537640349">"卸载该应用"</string>
+ <string name="cab_menu_app_info" msgid="914548323652698884">"应用详情"</string>
+ <string name="cab_app_selection_text" msgid="6378522164293415735">"选中了 1 个应用"</string>
<string name="cab_widget_selection_text" msgid="962527270506951955">"已选中 1 个窗口小部件"</string>
<string name="cab_folder_selection_text" msgid="8916111874189565067">"已选中 1 个文件夹"</string>
<string name="cab_shortcut_selection_text" msgid="8115847384500412878">"已选中 1 个快捷方式"</string>
<string name="permlab_install_shortcut" msgid="1201690825493376489">"安装快捷方式"</string>
- <string name="permdesc_install_shortcut" msgid="8634424803272077038">"允许应用程序自行添加快捷方式。"</string>
+ <string name="permdesc_install_shortcut" msgid="8634424803272077038">"允许应用自行添加快捷方式。"</string>
<string name="permlab_uninstall_shortcut" msgid="7696645932555926449">"卸载快捷方式"</string>
- <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"允许应用程序自行删除快捷方式,而无需用户干预。"</string>
+ <string name="permdesc_uninstall_shortcut" msgid="274355570620220977">"允许应用自行删除快捷方式,而无需用户干预。"</string>
<string name="permlab_read_settings" msgid="3452408290738106747">"读取主屏幕的设置和快捷方式"</string>
- <string name="permdesc_read_settings" msgid="5788109303585403679">"允许应用程序读取主屏幕中的设置和快捷方式。"</string>
+ <string name="permdesc_read_settings" msgid="5788109303585403679">"允许应用读取主屏幕中的设置和快捷方式。"</string>
<string name="permlab_write_settings" msgid="1360567537236705628">"写入主屏幕的设置和快捷方式"</string>
- <string name="permdesc_write_settings" msgid="8530105489115785531">"允许应用程序更改主屏幕中的设置和快捷方式。"</string>
+ <string name="permdesc_write_settings" msgid="8530105489115785531">"允许应用更改主屏幕中的设置和快捷方式。"</string>
<string name="gadget_error_text" msgid="8359351016167075858">"载入窗口小部件时出现问题"</string>
- <string name="uninstall_system_app_text" msgid="6429814133777046491">"这是系统应用程序,无法卸载。"</string>
+ <string name="uninstall_system_app_text" msgid="6429814133777046491">"这是系统应用,无法卸载。"</string>
<string name="dream_name" msgid="2847171357608437154">"Rocket Launcher"</string>
<string name="folder_hint_text" msgid="8633351560105748141">"未命名文件夹"</string>
<string name="default_scroll_format" msgid="4057140866420001240">"第 %1$d 页,共 %2$d 页"</string>
<string name="workspace_scroll_format" msgid="7911126267695001437">"工作区:第 %1$d 页,共 %2$d 页"</string>
- <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"应用程序:第 %1$d 页,共 %2$d 页"</string>
+ <string name="apps_customize_apps_scroll_format" msgid="5494241912377704885">"应用:第 %1$d 页,共 %2$d 页"</string>
<string name="apps_customize_widgets_scroll_format" msgid="5383009742241717437">"窗口小部件:第 %1$d 页,共 %2$d 页"</string>
<string name="workspace_cling_title" msgid="738396473989890567">"随意浏览"</string>
- <string name="workspace_cling_move_item" msgid="791013895761065070">"您可以在此处放置自己喜爱的应用程序。"</string>
- <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"要查看您的所有应用程序,请触摸该圆圈。"</string>
- <string name="all_apps_cling_title" msgid="2559734712581447107">"选择一些应用程序"</string>
- <string name="all_apps_cling_add_item" msgid="5665035103260318891">"要将某个应用程序添加到主屏幕,请触摸并按住该应用程序。"</string>
- <string name="folder_cling_title" msgid="4308949882377840953">"使用文件夹整理应用程序"</string>
- <string name="folder_cling_move_item" msgid="270598675060435169">"要移动应用程序,请触摸并按住该应用程序。"</string>
- <string name="folder_cling_create_folder" msgid="8352867485656129478">"要在主屏幕上创建新文件夹,请将一个应用程序叠放到另一个上。"</string>
+ <string name="workspace_cling_move_item" msgid="791013895761065070">"您可以在此处放置自己喜爱的应用。"</string>
+ <string name="workspace_cling_open_all_apps" msgid="2459977609848572588">"要查看您的所有应用,请触摸该圆圈。"</string>
+ <string name="all_apps_cling_title" msgid="2559734712581447107">"选择一些应用"</string>
+ <string name="all_apps_cling_add_item" msgid="5665035103260318891">"要将某个应用添加到主屏幕,请触摸并按住该应用。"</string>
+ <string name="folder_cling_title" msgid="4308949882377840953">"使用文件夹整理应用"</string>
+ <string name="folder_cling_move_item" msgid="270598675060435169">"要移动应用,请触摸并按住该应用。"</string>
+ <string name="folder_cling_create_folder" msgid="8352867485656129478">"要在主屏幕上创建新文件夹,请将一个应用叠放到另一个上。"</string>
<string name="cling_dismiss" msgid="2780907108735868381">"确定"</string>
<string name="folder_opened" msgid="1262064100943801533">"文件夹已打开,尺寸为 <xliff:g id="WIDTH">%1$d</xliff:g> × <xliff:g id="HEIGHT">%2$d</xliff:g>"</string>
<string name="folder_tap_to_close" msgid="1335478160661137579">"触摸可关闭文件夹"</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a9b14d0..509a670 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -82,7 +82,7 @@
<!-- Options in "Add to Home" dialog box; Title of the group containing the list of apps that can set the wallpaper-->
<string name="group_wallpapers">Wallpapers</string>
<!-- Error message when user has filled a home screen, possibly not used -->
- <string name="out_of_space">No more room on this Home screen.</string>
+ <string name="out_of_space">No more room on your Home screens.</string>
<!-- Error message when user tries to drop an invalid item on the hotseat -->
<string name="invalid_hotseat_item">This widget is too large for the hotseat.</string>
<!-- Message displayed when a shortcut is created by an external application -->
diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java
index e04ce64..4c0974f 100644
--- a/src/com/android/launcher2/InstallShortcutReceiver.java
+++ b/src/com/android/launcher2/InstallShortcutReceiver.java
@@ -17,9 +17,9 @@
package com.android.launcher2;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.widget.Toast;
@@ -27,10 +27,21 @@
import com.android.launcher.R;
import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
public class InstallShortcutReceiver extends BroadcastReceiver {
public static final String ACTION_INSTALL_SHORTCUT =
"com.android.launcher.action.INSTALL_SHORTCUT";
+ public static final String NEW_APPS_PAGE_KEY = "apps.new.page";
+ public static final String NEW_APPS_LIST_KEY = "apps.new.list";
+
+ public static final int NEW_SHORTCUT_BOUNCE_DURATION = 450;
+ public static final int NEW_SHORTCUT_STAGGER_DELAY = 75;
+
+ private static final int INSTALL_SHORTCUT_SUCCESSFUL = 0;
+ private static final int INSTALL_SHORTCUT_IS_DUPLICATE = -1;
+ private static final int INSTALL_SHORTCUT_NO_SPACE = -2;
// A mime-type representing shortcut data
public static final String SHORTCUT_MIMETYPE =
@@ -42,6 +53,8 @@
if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
return;
}
+ String spKey = LauncherApplication.getSharedPreferencesKey();
+ SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
final int screen = Launcher.getScreen();
final Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
@@ -62,26 +75,35 @@
}
final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context);
- final boolean shortcutExists = LauncherModel.shortcutExists(context, name, intent);
- final String[] errorMsgs = {""};
+ final boolean exists = LauncherModel.shortcutExists(context, name, intent);
+ final int[] result = {INSTALL_SHORTCUT_SUCCESSFUL};
- if (!installShortcut(context, data, items, name, intent, screen, shortcutExists,
- errorMsgs)) {
- // The target screen is full, let's try the other screens
- for (int i = 0; i < Launcher.SCREEN_COUNT; i++) {
- if (i != screen && installShortcut(context, data, items, name, intent, i,
- shortcutExists, errorMsgs)) break;
+ // Try adding the target to the workspace screens incrementally, starting at the current
+ // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1))
+ boolean found = false;
+ for (int i = 0; i < (2 * Launcher.SCREEN_COUNT) + 1 && !found; ++i) {
+ int si = screen + (int) ((i / 2f) + 0.5f) * ((i % 2 == 1) ? 1 : -1);
+ if (0 <= si && si < Launcher.SCREEN_COUNT) {
+ found = installShortcut(context, data, items, name, intent, si, exists, sp, result);
}
}
- if (!errorMsgs[0].isEmpty()) {
- Toast.makeText(context, errorMsgs[0],
- Toast.LENGTH_SHORT).show();
+ // We only report error messages (duplicate shortcut or out of space) as the add-animation
+ // will provide feedback otherwise
+ if (!found) {
+ if (result[0] == INSTALL_SHORTCUT_NO_SPACE) {
+ Toast.makeText(context, context.getString(R.string.out_of_space),
+ Toast.LENGTH_SHORT).show();
+ } else if (result[0] == INSTALL_SHORTCUT_IS_DUPLICATE) {
+ Toast.makeText(context, context.getString(R.string.shortcut_duplicate, name),
+ Toast.LENGTH_SHORT).show();
+ }
}
}
private boolean installShortcut(Context context, Intent data, ArrayList<ItemInfo> items,
- String name, Intent intent, int screen, boolean shortcutExists, String[] errorMsgs) {
+ String name, Intent intent, int screen, boolean shortcutExists,
+ SharedPreferences sharedPrefs, int[] result) {
if (findEmptyCell(context, items, mCoordinates, screen)) {
if (intent != null) {
if (intent.getAction() == null) {
@@ -92,23 +114,35 @@
// different places)
boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
if (duplicate || !shortcutExists) {
+ // If the new app is going to fall into the same page as before, then just
+ // continue adding to the current page
+ int newAppsScreen = sharedPrefs.getInt(NEW_APPS_PAGE_KEY, screen);
+ Set<String> newApps = new HashSet<String>();
+ if (newAppsScreen == screen) {
+ newApps = sharedPrefs.getStringSet(NEW_APPS_LIST_KEY, newApps);
+ }
+ newApps.add(intent.toUri(0).toString());
+ sharedPrefs.edit()
+ .putInt(NEW_APPS_PAGE_KEY, screen)
+ .putStringSet(NEW_APPS_LIST_KEY, newApps)
+ .commit();
+
+ // Update the Launcher db
LauncherApplication app = (LauncherApplication) context.getApplicationContext();
ShortcutInfo info = app.getModel().addShortcut(context, data,
- LauncherSettings.Favorites.CONTAINER_DESKTOP, screen, mCoordinates[0],
- mCoordinates[1], true);
- if (info != null) {
- errorMsgs[0] = context.getString(R.string.shortcut_installed, name);
- } else {
+ LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
+ mCoordinates[0], mCoordinates[1], true);
+ if (info == null) {
return false;
}
} else {
- errorMsgs[0] = context.getString(R.string.shortcut_duplicate, name);
+ result[0] = INSTALL_SHORTCUT_IS_DUPLICATE;
}
return true;
}
} else {
- errorMsgs[0] = context.getString(R.string.out_of_space);
+ result[0] = INSTALL_SHORTCUT_NO_SPACE;
}
return false;
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 0c1b76f..9494d27 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -55,6 +55,7 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Debug;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
@@ -84,6 +85,7 @@
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
+import android.view.animation.BounceInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.Advanceable;
@@ -103,7 +105,12 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
/**
* Default launcher application.
@@ -253,6 +260,10 @@
// it from the context.
private SharedPreferences mSharedPrefs;
+ // Holds the page that we need to animate to, and the icon views that we need to animate up
+ // when we scroll to that page on resume.
+ private int mNewShortcutAnimatePage = -1;
+ private ArrayList<View> mNewShortcutAnimateViews = new ArrayList<View>();
private BubbleTextView mWaitingForResume;
@@ -280,7 +291,8 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LauncherApplication app = ((LauncherApplication)getApplication());
- mSharedPrefs = getSharedPreferences(PREFS_KEY, Context.MODE_PRIVATE);
+ mSharedPrefs = getSharedPreferences(LauncherApplication.getSharedPreferencesKey(),
+ Context.MODE_PRIVATE);
mModel = app.setLauncher(this);
mIconCache = app.getIconCache();
mDragController = new DragController(this);
@@ -317,7 +329,7 @@
}
if (!mRestoring) {
- mModel.startLoader(this, true);
+ mModel.startLoader(true);
}
if (!mModel.isAllAppsLoaded()) {
@@ -593,10 +605,11 @@
@Override
protected void onResume() {
super.onResume();
+
mPaused = false;
if (mRestoring || mOnResumeNeedsLoad) {
mWorkspaceLoading = true;
- mModel.startLoader(this, true);
+ mModel.startLoader(true);
mRestoring = false;
mOnResumeNeedsLoad = false;
}
@@ -725,7 +738,7 @@
showAllApps(false);
}
- final int currentScreen = savedState.getInt(RUNTIME_STATE_CURRENT_SCREEN, -1);
+ int currentScreen = savedState.getInt(RUNTIME_STATE_CURRENT_SCREEN, -1);
if (currentScreen > -1) {
mWorkspace.setCurrentPage(currentScreen);
}
@@ -2184,7 +2197,7 @@
if (mWorkspaceLoading) {
lockAllApps();
- mModel.startLoader(Launcher.this, false);
+ mModel.startLoader(false);
} else {
final FolderIcon folderIcon = (FolderIcon)
mWorkspace.getViewForTag(mFolderInfo);
@@ -2196,7 +2209,7 @@
} else {
lockAllApps();
mWorkspaceLoading = true;
- mModel.startLoader(Launcher.this, false);
+ mModel.startLoader(false);
}
}
}
@@ -3076,7 +3089,6 @@
}
}
-
/**
* Refreshes the shortcuts shown on the workspace.
*
@@ -3085,6 +3097,8 @@
public void startBinding() {
final Workspace workspace = mWorkspace;
+ mNewShortcutAnimatePage = -1;
+ mNewShortcutAnimateViews.clear();
mWorkspace.clearDropTargets();
int count = workspace.getChildCount();
for (int i = 0; i < count; i++) {
@@ -3106,8 +3120,12 @@
public void bindItems(ArrayList<ItemInfo> shortcuts, int start, int end) {
setLoadOnResume();
- final Workspace workspace = mWorkspace;
- for (int i=start; i<end; i++) {
+ // Get the list of added shortcuts and intersect them with the set of shortcuts here
+ Set<String> newApps = new HashSet<String>();
+ newApps = mSharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps);
+
+ Workspace workspace = mWorkspace;
+ for (int i = start; i < end; i++) {
final ItemInfo item = shortcuts.get(i);
// Short circuit if we are loading dock items for a configuration which has no dock
@@ -3119,9 +3137,23 @@
switch (item.itemType) {
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
- View shortcut = createShortcut((ShortcutInfo)item);
+ ShortcutInfo info = (ShortcutInfo) item;
+ String uri = info.intent.toUri(0).toString();
+ View shortcut = createShortcut(info);
workspace.addInScreen(shortcut, item.container, item.screen, item.cellX,
item.cellY, 1, 1, false);
+ if (newApps.contains(uri)) {
+ newApps.remove(uri);
+
+ // Prepare the view to be animated up
+ shortcut.setAlpha(0f);
+ shortcut.setScaleX(0f);
+ shortcut.setScaleY(0f);
+ mNewShortcutAnimatePage = item.screen;
+ if (!mNewShortcutAnimateViews.contains(shortcut)) {
+ mNewShortcutAnimateViews.add(shortcut);
+ }
+ }
break;
case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this,
@@ -3132,6 +3164,7 @@
break;
}
}
+
workspace.requestLayout();
}
@@ -3169,11 +3202,6 @@
item.hostView.setAppWidget(appWidgetId, appWidgetInfo);
item.hostView.setTag(item);
- // We need to load the minimum span and embed it into the item info
- int[] minSpan = getMinSpanForWidget(appWidgetInfo, null);
- item.minSpanX = minSpan[0];
- item.minSpanY = minSpan[1];
-
workspace.addInScreen(item.hostView, item.container, item.screen, item.cellX,
item.cellY, item.spanX, item.spanY, false);
@@ -3207,8 +3235,6 @@
mSavedInstanceState = null;
}
- mWorkspaceLoading = false;
-
// If we received the result of any pending adds while the loader was running (e.g. the
// widget configuration forced an orientation change), process them now.
for (int i = 0; i < sPendingAddList.size(); i++) {
@@ -3220,7 +3246,72 @@
// package changes in bindSearchablesChanged()
updateAppMarketIcon();
- mWorkspace.postDelayed(mBuildLayersRunnable, 500);
+ // Animate up any icons as necessary
+ if (mVisible || mWorkspaceLoading) {
+ Runnable newAppsRunnable = new Runnable() {
+ @Override
+ public void run() {
+ runNewAppsAnimation();
+ }
+ };
+ if (mNewShortcutAnimatePage > -1 &&
+ mNewShortcutAnimatePage != mWorkspace.getCurrentPage()) {
+ mWorkspace.snapToPage(mNewShortcutAnimatePage, newAppsRunnable);
+ } else {
+ newAppsRunnable.run();
+ }
+ }
+
+ mWorkspaceLoading = false;
+ }
+
+ /**
+ * Runs a new animation that scales up icons that were added while Launcher was in the
+ * background.
+ */
+ private void runNewAppsAnimation() {
+ AnimatorSet anim = new AnimatorSet();
+ Collection<Animator> bounceAnims = new ArrayList<Animator>();
+ Collections.sort(mNewShortcutAnimateViews, new Comparator<View>() {
+ @Override
+ public int compare(View a, View b) {
+ CellLayout.LayoutParams alp = (CellLayout.LayoutParams) a.getLayoutParams();
+ CellLayout.LayoutParams blp = (CellLayout.LayoutParams) b.getLayoutParams();
+ int cellCountX = LauncherModel.getCellCountX();
+ return (alp.cellY * cellCountX + alp.cellX) - (blp.cellY * cellCountX + blp.cellX);
+ }
+ });
+ for (int i = 0; i < mNewShortcutAnimateViews.size(); ++i) {
+ View v = mNewShortcutAnimateViews.get(i);
+ ValueAnimator bounceAnim = ObjectAnimator.ofPropertyValuesHolder(v,
+ PropertyValuesHolder.ofFloat("alpha", 1f),
+ PropertyValuesHolder.ofFloat("scaleX", 1f),
+ PropertyValuesHolder.ofFloat("scaleY", 1f));
+ bounceAnim.setDuration(InstallShortcutReceiver.NEW_SHORTCUT_BOUNCE_DURATION);
+ bounceAnim.setStartDelay(i * InstallShortcutReceiver.NEW_SHORTCUT_STAGGER_DELAY);
+ bounceAnim.setInterpolator(new SmoothPagedView.OvershootInterpolator());
+ bounceAnims.add(bounceAnim);
+ }
+ anim.playTogether(bounceAnims);
+ anim.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mWorkspace.postDelayed(mBuildLayersRunnable, 500);
+ }
+ });
+ anim.start();
+
+ // Clean up
+ mNewShortcutAnimatePage = -1;
+ mNewShortcutAnimateViews.clear();
+ new Thread("clearNewAppsThread") {
+ public void run() {
+ mSharedPrefs.edit()
+ .putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, -1)
+ .putStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, null)
+ .commit();
+ }
+ }.start();
}
@Override
@@ -3363,7 +3454,6 @@
}
/* Cling related */
- private static final String PREFS_KEY = "com.android.launcher2.prefs";
private boolean isClingsEnabled() {
// disable clings when running in a test harness
if(ActivityManager.isRunningInTestHarness()) return false;
diff --git a/src/com/android/launcher2/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index 47ce0b7..ef1eb5f 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -37,6 +37,7 @@
private static boolean sIsScreenLarge;
private static float sScreenDensity;
private static int sLongPressTimeout = 300;
+ private static final String sSharedPreferencesKey = "com.android.launcher2.prefs";
WeakReference<LauncherProvider> mLauncherProvider;
@Override
@@ -94,7 +95,10 @@
private final ContentObserver mFavoritesObserver = new ContentObserver(new Handler()) {
@Override
public void onChange(boolean selfChange) {
- mModel.startLoader(LauncherApplication.this, false);
+ // If the database has ever changed, then we really need to force a reload of the
+ // workspace on the next load
+ mModel.resetLoadedState(false, true);
+ mModel.startLoaderFromBackground();
}
};
@@ -119,6 +123,10 @@
return mLauncherProvider.get();
}
+ public static String getSharedPreferencesKey() {
+ return sSharedPreferencesKey;
+ }
+
public static boolean isScreenLarge() {
return sIsScreenLarge;
}
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 159ddb0..30eb86c 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -649,19 +649,24 @@
}
private void forceReload() {
- synchronized (mLock) {
- // Stop any existing loaders first, so they don't set mAllAppsLoaded or
- // mWorkspaceLoaded to true later
- stopLoaderLocked();
- mAllAppsLoaded = false;
- mWorkspaceLoaded = false;
- }
+ resetLoadedState(true, true);
+
// Do this here because if the launcher activity is running it will be restarted.
// If it's not running startLoaderFromBackground will merely tell it that it needs
// to reload.
startLoaderFromBackground();
}
+ public void resetLoadedState(boolean resetAllAppsLoaded, boolean resetWorkspaceLoaded) {
+ synchronized (mLock) {
+ // Stop any existing loaders first, so they don't set mAllAppsLoaded or
+ // mWorkspaceLoaded to true later
+ stopLoaderLocked();
+ if (resetAllAppsLoaded) mAllAppsLoaded = false;
+ if (resetWorkspaceLoaded) mWorkspaceLoaded = false;
+ }
+ }
+
/**
* When the launcher is in the background, it's possible for it to miss paired
* configuration changes. So whenever we trigger the loader from the background
@@ -680,7 +685,7 @@
}
}
if (runLoader) {
- startLoader(mApp, false);
+ startLoader(false);
}
}
@@ -698,7 +703,7 @@
return isLaunching;
}
- public void startLoader(Context context, boolean isLaunching) {
+ public void startLoader(boolean isLaunching) {
synchronized (mLock) {
if (DEBUG_LOADERS) {
Log.d(TAG, "startLoader isLaunching=" + isLaunching);
@@ -709,7 +714,7 @@
// If there is already one running, tell it to stop.
// also, don't downgrade isLaunching if we're already running
isLaunching = isLaunching || stopLoaderLocked();
- mLoaderTask = new LoaderTask(context, isLaunching);
+ mLoaderTask = new LoaderTask(mApp, isLaunching);
sWorkerThread.setPriority(Thread.NORM_PRIORITY);
sWorker.post(mLoaderTask);
}
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 0854508..5434704 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -62,7 +62,8 @@
// the min drag distance for a fling to register, to prevent random page shifts
private static final int MIN_LENGTH_FOR_FLING = 25;
- private static final int PAGE_SNAP_ANIMATION_DURATION = 550;
+ protected static final int PAGE_SNAP_ANIMATION_DURATION = 550;
+ protected static final int SLOW_PAGE_SNAP_ANIMATION_DURATION = 950;
protected static final float NANOTIME_DIV = 1000000000.0f;
private static final float OVERSCROLL_ACCELERATE_FACTOR = 2;
diff --git a/src/com/android/launcher2/SmoothPagedView.java b/src/com/android/launcher2/SmoothPagedView.java
index fe763f5..e6414d9 100644
--- a/src/com/android/launcher2/SmoothPagedView.java
+++ b/src/com/android/launcher2/SmoothPagedView.java
@@ -35,11 +35,11 @@
private Interpolator mScrollInterpolator;
- private static class WorkspaceOvershootInterpolator implements Interpolator {
+ public static class OvershootInterpolator implements Interpolator {
private static final float DEFAULT_TENSION = 1.3f;
private float mTension;
- public WorkspaceOvershootInterpolator() {
+ public OvershootInterpolator() {
mTension = DEFAULT_TENSION;
}
@@ -101,7 +101,7 @@
if (mScrollMode == DEFAULT_MODE) {
mBaseLineFlingVelocity = 2500.0f;
mFlingVelocityInfluence = 0.4f;
- mScrollInterpolator = new WorkspaceOvershootInterpolator();
+ mScrollInterpolator = new OvershootInterpolator();
mScroller = new Scroller(getContext(), mScrollInterpolator);
}
}
@@ -139,9 +139,9 @@
}
if (settle) {
- ((WorkspaceOvershootInterpolator) mScrollInterpolator).setDistance(screenDelta);
+ ((OvershootInterpolator) mScrollInterpolator).setDistance(screenDelta);
} else {
- ((WorkspaceOvershootInterpolator) mScrollInterpolator).disableSettle();
+ ((OvershootInterpolator) mScrollInterpolator).disableSettle();
}
velocity = Math.abs(velocity);
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 1a65fc2..f1941b3 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -184,6 +184,7 @@
WallpaperOffsetInterpolator mWallpaperOffset;
boolean mUpdateWallpaperOffsetImmediately = false;
private Runnable mDelayedResizeRunnable;
+ private Runnable mDelayedSnapToPageRunnable;
private int mDisplayWidth;
private int mDisplayHeight;
private boolean mIsStaticWallpaper;
@@ -766,6 +767,11 @@
mDelayedResizeRunnable.run();
mDelayedResizeRunnable = null;
}
+
+ if (mDelayedSnapToPageRunnable != null) {
+ mDelayedSnapToPageRunnable.run();
+ mDelayedSnapToPageRunnable = null;
+ }
}
@Override
@@ -907,6 +913,20 @@
computeWallpaperScrollRatio(whichPage);
}
+ @Override
+ protected void snapToPage(int whichPage, int duration) {
+ super.snapToPage(whichPage, duration);
+ computeWallpaperScrollRatio(whichPage);
+ }
+
+ protected void snapToPage(int whichPage, Runnable r) {
+ if (mDelayedSnapToPageRunnable != null) {
+ mDelayedSnapToPageRunnable.run();
+ }
+ mDelayedSnapToPageRunnable = r;
+ snapToPage(whichPage, SLOW_PAGE_SNAP_ANIMATION_DURATION);
+ }
+
private void computeWallpaperScrollRatio(int page) {
// Here, we determine what the desired scroll would be with and without a layout scale,
// and compute a ratio between the two. This allows us to adjust the wallpaper offset