diff options
author | Winson Chung <winsonc@google.com> | 2012-04-03 14:22:34 -0700 |
---|---|---|
committer | Winson Chung <winsonc@google.com> | 2012-04-09 17:04:00 -0700 |
commit | a2413751e3a698aef9c87411a639637883856939 (patch) | |
tree | e71fc7aa7fef5408ca7956c5ad373504d763337c /src | |
parent | e9bafe991b5bbcd033e1f27c66ba254d55117b20 (diff) | |
download | android_packages_apps_Trebuchet-a2413751e3a698aef9c87411a639637883856939.tar.gz android_packages_apps_Trebuchet-a2413751e3a698aef9c87411a639637883856939.tar.bz2 android_packages_apps_Trebuchet-a2413751e3a698aef9c87411a639637883856939.zip |
Adding delay upon user interaction to prevent the new-app animation from taking over your phone. (Bug 6248609)
- Fixing issue where we might have been reading the db items while handling previous broadcast and adding db items to invalid positions
- Making items add alternating from the center page (as opposed to the current page)
- Re-adding the strict-mode fix (really requires 1. to be true)
- Adding flag for enabling strict mode exceptions
- Removing items from the new apps add list on uninstall-shortcut broadcast
Change-Id: I495e80bf5f8dbb4b87dd709460937d6f2a1e05e7
Diffstat (limited to 'src')
-rw-r--r-- | src/com/android/launcher2/DragController.java | 14 | ||||
-rw-r--r-- | src/com/android/launcher2/InstallShortcutReceiver.java | 42 | ||||
-rw-r--r-- | src/com/android/launcher2/Launcher.java | 100 | ||||
-rw-r--r-- | src/com/android/launcher2/UninstallShortcutReceiver.java | 35 |
4 files changed, 149 insertions, 42 deletions
diff --git a/src/com/android/launcher2/DragController.java b/src/com/android/launcher2/DragController.java index 2a1d65adc..9a61db666 100644 --- a/src/com/android/launcher2/DragController.java +++ b/src/com/android/launcher2/DragController.java @@ -440,6 +440,19 @@ public class DragController { return mTmpPoint; } + private long mLastTouchUpTime = -1; + long getLastGestureUpTime() { + if (mDragging) { + return System.currentTimeMillis(); + } else { + return mLastTouchUpTime; + } + } + + void resetLastGestureUpTime() { + mLastTouchUpTime = -1; + } + /** * Call this from a drag source view. */ @@ -467,6 +480,7 @@ public class DragController { mLastDropTarget = null; break; case MotionEvent.ACTION_UP: + mLastTouchUpTime = System.currentTimeMillis(); if (mDragging) { PointF vec = isFlingingToDelete(mDragObject.dragSource); if (vec != null) { diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java index 4c0974fd3..19b1c69d2 100644 --- a/src/com/android/launcher2/InstallShortcutReceiver.java +++ b/src/com/android/launcher2/InstallShortcutReceiver.java @@ -56,7 +56,6 @@ public class InstallShortcutReceiver extends BroadcastReceiver { 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); if (intent == null) { return; @@ -74,17 +73,23 @@ public class InstallShortcutReceiver extends BroadcastReceiver { } } - final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context); - final boolean exists = LauncherModel.shortcutExists(context, name, intent); + // Lock on the app so that we don't try and get the items while apps are being added + LauncherApplication app = (LauncherApplication) context.getApplicationContext(); final int[] result = {INSTALL_SHORTCUT_SUCCESSFUL}; - - // 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); + synchronized (app) { + final ArrayList<ItemInfo> items = LauncherModel.getItemsInLocalCoordinates(context); + final boolean exists = LauncherModel.shortcutExists(context, name, intent); + + // Try adding to the workspace screens incrementally, starting at the default or center + // screen and alternating between +1, -1, +2, -2, etc. (using ~ ceil(i/2f)*(-1)^(i-1)) + final int screen = Launcher.DEFAULT_SCREEN; + 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); + } } } @@ -102,8 +107,8 @@ public class InstallShortcutReceiver extends BroadcastReceiver { } private boolean installShortcut(Context context, Intent data, ArrayList<ItemInfo> items, - String name, Intent intent, int screen, boolean shortcutExists, - SharedPreferences sharedPrefs, int[] result) { + String name, Intent intent, final int screen, boolean shortcutExists, + final SharedPreferences sharedPrefs, int[] result) { if (findEmptyCell(context, items, mCoordinates, screen)) { if (intent != null) { if (intent.getAction() == null) { @@ -122,10 +127,15 @@ public class InstallShortcutReceiver extends BroadcastReceiver { 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(); + final Set<String> savedNewApps = newApps; + new Thread("setNewAppsThread") { + public void run() { + sharedPrefs.edit() + .putInt(NEW_APPS_PAGE_KEY, screen) + .putStringSet(NEW_APPS_LIST_KEY, savedNewApps) + .commit(); + } + }.start(); // Update the Launcher db LauncherApplication app = (LauncherApplication) context.getApplicationContext(); diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index b3ce96884..cef713763 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -55,10 +55,10 @@ import android.graphics.drawable.Drawable; 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; +import android.os.StrictMode; import android.os.SystemClock; import android.os.SystemProperties; import android.provider.Settings; @@ -85,7 +85,6 @@ import android.view.WindowManager; 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; @@ -123,6 +122,7 @@ public final class Launcher extends Activity static final boolean PROFILE_STARTUP = false; static final boolean DEBUG_WIDGETS = false; + static final boolean DEBUG_STRICT_MODE = false; private static final int MENU_GROUP_WALLPAPER = 1; private static final int MENU_WALLPAPER_SETTINGS = Menu.FIRST + 1; @@ -182,6 +182,9 @@ public final class Launcher extends Activity private static final Object sLock = new Object(); private static int sScreen = DEFAULT_SCREEN; + // How long to wait before the new-shortcut animation automatically pans the workspace + private static int NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS = 10; + private final BroadcastReceiver mCloseSystemDialogsReceiver = new CloseSystemDialogsIntentReceiver(); private final ContentObserver mWidgetObserver = new AppWidgetResetObserver(); @@ -289,6 +292,21 @@ public final class Launcher extends Activity @Override protected void onCreate(Bundle savedInstanceState) { + if (DEBUG_STRICT_MODE) { + StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder() + .detectDiskReads() + .detectDiskWrites() + .detectNetwork() // or .detectAll() for all detectable problems + .penaltyLog() + .build()); + StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder() + .detectLeakedSqlLiteObjects() + .detectLeakedClosableObjects() + .penaltyLog() + .penaltyDeath() + .build()); + } + super.onCreate(savedInstanceState); LauncherApplication app = ((LauncherApplication)getApplication()); mSharedPrefs = getSharedPreferences(LauncherApplication.getSharedPreferencesKey(), @@ -635,6 +653,7 @@ public final class Launcher extends Activity super.onPause(); mPaused = true; mDragController.cancelDrag(); + mDragController.resetLastGestureUpTime(); } @Override @@ -3258,27 +3277,46 @@ public final class Launcher extends Activity Runnable newAppsRunnable = new Runnable() { @Override public void run() { - runNewAppsAnimation(); + runNewAppsAnimation(false); } }; - if (mNewShortcutAnimatePage > -1 && - mNewShortcutAnimatePage != mWorkspace.getCurrentPage()) { - mWorkspace.snapToPage(mNewShortcutAnimatePage, newAppsRunnable); + + boolean willSnapPage = mNewShortcutAnimatePage > -1 && + mNewShortcutAnimatePage != mWorkspace.getCurrentPage(); + if (canRunNewAppsAnimation()) { + // If the user has not interacted recently, then either snap to the new page to show + // the new-apps animation or just run them if they are to appear on the current page + if (willSnapPage) { + mWorkspace.snapToPage(mNewShortcutAnimatePage, newAppsRunnable); + } else { + runNewAppsAnimation(false); + } } else { - newAppsRunnable.run(); + // If the user has interacted recently, then run the animations immediately if they + // are on another page (or just normally if they are added to the current page) + runNewAppsAnimation(willSnapPage); } } mWorkspaceLoading = false; } + private boolean canRunNewAppsAnimation() { + long diff = System.currentTimeMillis() - mDragController.getLastGestureUpTime(); + return diff > (NEW_APPS_ANIMATION_INACTIVE_TIMEOUT_SECONDS * 1000); + } + /** * Runs a new animation that scales up icons that were added while Launcher was in the * background. + * + * @param immediate whether to run the animation or show the results immediately */ - private void runNewAppsAnimation() { + private void runNewAppsAnimation(boolean immediate) { AnimatorSet anim = new AnimatorSet(); Collection<Animator> bounceAnims = new ArrayList<Animator>(); + + // Order these new views spatially so that they animate in order Collections.sort(mNewShortcutAnimateViews, new Comparator<View>() { @Override public int compare(View a, View b) { @@ -3288,25 +3326,35 @@ public final class Launcher extends Activity 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); + + // Animate each of the views in place (or show them immediately if requested) + if (immediate) { + for (View v : mNewShortcutAnimateViews) { + v.setAlpha(1f); + v.setScaleX(1f); + v.setScaleY(1f); } - }); - anim.start(); + } else { + 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; diff --git a/src/com/android/launcher2/UninstallShortcutReceiver.java b/src/com/android/launcher2/UninstallShortcutReceiver.java index eb4ee4cf3..3f6de7c5a 100644 --- a/src/com/android/launcher2/UninstallShortcutReceiver.java +++ b/src/com/android/launcher2/UninstallShortcutReceiver.java @@ -20,11 +20,14 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.ContentResolver; +import android.content.SharedPreferences; import android.database.Cursor; import android.net.Uri; import android.widget.Toast; import java.net.URISyntaxException; +import java.util.HashSet; +import java.util.Set; import com.android.launcher.R; @@ -36,7 +39,16 @@ public class UninstallShortcutReceiver extends BroadcastReceiver { if (!ACTION_UNINSTALL_SHORTCUT.equals(data.getAction())) { return; } + String spKey = LauncherApplication.getSharedPreferencesKey(); + SharedPreferences sharedPrefs = context.getSharedPreferences(spKey, Context.MODE_PRIVATE); + LauncherApplication app = (LauncherApplication) context.getApplicationContext(); + synchronized (app) { + removeShortcut(context, data, sharedPrefs); + } + } + + private void removeShortcut(Context context, Intent data, final SharedPreferences sharedPrefs) { Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT); String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME); boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true); @@ -77,6 +89,29 @@ public class UninstallShortcutReceiver extends BroadcastReceiver { Toast.makeText(context, context.getString(R.string.shortcut_uninstalled, name), Toast.LENGTH_SHORT).show(); } + + // Remove any items due to be animated + boolean appRemoved; + Set<String> newApps = new HashSet<String>(); + newApps = sharedPrefs.getStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, newApps); + do { + appRemoved = newApps.remove(intent.toUri(0).toString()); + } while (appRemoved); + if (appRemoved) { + final Set<String> savedNewApps = newApps; + new Thread("setNewAppsThread-remove") { + public void run() { + SharedPreferences.Editor editor = sharedPrefs.edit(); + editor.putStringSet(InstallShortcutReceiver.NEW_APPS_LIST_KEY, + savedNewApps); + if (savedNewApps.isEmpty()) { + // Reset the page index if there are no more items + editor.putInt(InstallShortcutReceiver.NEW_APPS_PAGE_KEY, -1); + } + editor.commit(); + } + }.start(); + } } } } |