summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/launcher2/BubbleTextView.java3
-rw-r--r--src/com/android/launcher2/CacheableTextView.java172
-rw-r--r--src/com/android/launcher2/CellLayout.java8
-rw-r--r--src/com/android/launcher2/HolographicOutlineHelper.java2
-rw-r--r--src/com/android/launcher2/IconCache.java2
-rw-r--r--src/com/android/launcher2/Launcher.java88
-rw-r--r--src/com/android/launcher2/LauncherAppWidgetHost.java6
-rw-r--r--src/com/android/launcher2/LauncherModel.java3
-rw-r--r--src/com/android/launcher2/PagedView.java8
-rw-r--r--src/com/android/launcher2/PagedViewIcon.java4
-rw-r--r--src/com/android/launcher2/PagedViewWithDraggableItems.java6
-rw-r--r--src/com/android/launcher2/Workspace.java213
12 files changed, 280 insertions, 235 deletions
diff --git a/src/com/android/launcher2/BubbleTextView.java b/src/com/android/launcher2/BubbleTextView.java
index 4d1dbf8..f3aa342 100644
--- a/src/com/android/launcher2/BubbleTextView.java
+++ b/src/com/android/launcher2/BubbleTextView.java
@@ -37,7 +37,7 @@ import android.view.View;
* because we want to make the bubble taller than the text and TextView's clip is
* too aggressive.
*/
-public class BubbleTextView extends CacheableTextView implements VisibilityChangedBroadcaster {
+public class BubbleTextView extends CachedTextView implements VisibilityChangedBroadcaster {
static final float CORNER_RADIUS = 4.0f;
static final float SHADOW_LARGE_RADIUS = 4.0f;
static final float SHADOW_SMALL_RADIUS = 1.75f;
@@ -118,7 +118,6 @@ public class BubbleTextView extends CacheableTextView implements VisibilityChang
new FastBitmapDrawable(b),
null, null);
setText(info.title);
- buildAndEnableCache();
setTag(info);
}
diff --git a/src/com/android/launcher2/CacheableTextView.java b/src/com/android/launcher2/CacheableTextView.java
deleted file mode 100644
index da2f302..0000000
--- a/src/com/android/launcher2/CacheableTextView.java
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- * Copyright (C) 2010 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.launcher2;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.text.Layout;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-/*
- * This class is a bit of a hack, designed to speed up long text labels in Launcher. It caches the
- * text in a TextView to a bitmap and then just draws that Bitmap instead afterward, speeding up
- * rendering. Marquee scrolling is not currently supported.
- *
- */
-public class CacheableTextView extends TextView {
- private Bitmap mCache;
- private final Paint mCachePaint = new Paint();
- private final Canvas mCacheCanvas = new Canvas();
-
- private int mPrevAlpha = -1;
- private boolean mIsBuildingCache;
- boolean mWaitingToGenerateCache;
- float mTextCacheLeft;
- float mTextCacheTop;
- float mTextCacheScrollX;
- float mRectLeft, mRectTop;
- private float mPaddingH = 0;
- private float mPaddingV = 0;
- private CharSequence mText;
-
- public CacheableTextView(Context context) {
- super(context);
- }
-
- public CacheableTextView(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public CacheableTextView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- protected int getCacheTopPadding() {
- return 0;
- }
- protected int getCacheLeftPadding() {
- return 0;
- }
- protected int getCacheRightPadding() {
- return 0;
- }
- protected int getCacheBottomPadding() {
- return 0;
- }
-
- public void buildAndEnableCache() {
- // Defers building the cache until the next draw to allow measuring
- // and laying out.
- buildAndEnableCache(false);
- }
-
- public void buildAndEnableCache(boolean isImmediate) {
- if (getLayout() == null || !isImmediate) {
- mWaitingToGenerateCache = true;
- return;
- }
-
- final Layout layout = getLayout();
- final int left = getCompoundPaddingLeft();
- final int top = getExtendedPaddingTop();
- final float prevAlpha = getAlpha();
-
- mTextCacheLeft = layout.getLineLeft(0) - getCacheLeftPadding();
- mTextCacheTop = top + layout.getLineTop(0) - mPaddingV - getCacheTopPadding();
-
- mRectLeft = mScrollX + getLeft();
- mRectTop = 0;
- mTextCacheScrollX = mScrollX;
-
- final float textCacheRight =
- Math.min(left + layout.getLineRight(0) + mPaddingH, mScrollX + mRight - mLeft) +
- getCacheRightPadding();
- final float textCacheBottom = top + layout.getLineBottom(0) + mPaddingV +
- getCacheBottomPadding();
- final float xCharWidth = getPaint().measureText("x");
-
- int width = (int) (textCacheRight - mTextCacheLeft + (2 * xCharWidth));
- int height = (int) (textCacheBottom - mTextCacheTop);
-
- if (width != 0 && height != 0) {
- if (mCache != null) {
- if (mCache.getWidth() != width || mCache.getHeight() != height) {
- mCache.recycle();
- mCache = null;
- }
- }
- if (mCache == null) {
- mCache = Bitmap.createBitmap(width, height, Config.ARGB_8888);
- mCacheCanvas.setBitmap(mCache);
- } else {
- mCacheCanvas.drawColor(0x00000000);
- }
-
- mCacheCanvas.save();
- mCacheCanvas.translate(-mTextCacheLeft, -mTextCacheTop);
-
- mIsBuildingCache = true;
- setAlpha(1.0f);
- draw(mCacheCanvas);
- setAlpha(prevAlpha);
- mIsBuildingCache = false;
- mCacheCanvas.restore();
-
- // A hack-- we set the text to be one space (we don't make it empty just to avoid any
- // potential issues with text measurement, like line height, etc.) so that the text view
- // doesn't draw it anymore, since it's been cached. We have to manually rebuild
- // the cache whenever the text is changed (which is never in Launcher)
- mText = getText();
- setText(" ");
- }
- }
-
- public CharSequence getText() {
- return (mText == null) ? super.getText() : mText;
- }
-
- public void draw(Canvas canvas) {
- if (mWaitingToGenerateCache && !mIsBuildingCache) {
- buildAndEnableCache(true);
- mWaitingToGenerateCache = false;
- }
- if (mCache != null && !mIsBuildingCache) {
- canvas.drawBitmap(mCache, mTextCacheLeft - mTextCacheScrollX + mScrollX,
- mTextCacheTop, mCachePaint);
- }
- super.draw(canvas);
- }
-
- protected boolean isBuildingCache() {
- return mIsBuildingCache;
- }
-
- @Override
- protected boolean onSetAlpha(int alpha) {
- if (mPrevAlpha != alpha) {
- mPrevAlpha = alpha;
- mCachePaint.setAlpha(alpha);
- super.onSetAlpha(alpha);
- }
- return true;
- }
-}
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java
index fd389ca..45de630 100644
--- a/src/com/android/launcher2/CellLayout.java
+++ b/src/com/android/launcher2/CellLayout.java
@@ -417,7 +417,7 @@ public class CellLayout extends ViewGroup implements Dimmable, VisibilityChanged
}
public void updateCache() {
- mCacheCanvas.drawColor(0x00000000, Mode.CLEAR);
+ mCacheCanvas.drawColor(0, Mode.CLEAR);
float alpha = getAlpha();
setAlpha(1.0f);
@@ -625,6 +625,7 @@ public class CellLayout extends ViewGroup implements Dimmable, VisibilityChanged
child.setId(childId);
addView(child, index, lp);
+ child.setAlpha(getAlpha());
if (child instanceof VisibilityChangedBroadcaster) {
VisibilityChangedBroadcaster v = (VisibilityChangedBroadcaster) child;
v.setVisibilityChangedListener(this);
@@ -972,6 +973,7 @@ public class CellLayout extends ViewGroup implements Dimmable, VisibilityChanged
}
}
prepareCacheBitmap();
+ invalidateCache();
}
@Override
@@ -1388,7 +1390,9 @@ public class CellLayout extends ViewGroup implements Dimmable, VisibilityChanged
lp.isDragging = false;
lp.dropped = true;
lp.animateDrop = animate;
- child.setVisibility(View.INVISIBLE);
+ if (animate) {
+ child.setVisibility(View.INVISIBLE);
+ }
child.requestLayout();
}
}
diff --git a/src/com/android/launcher2/HolographicOutlineHelper.java b/src/com/android/launcher2/HolographicOutlineHelper.java
index 6d0899d..1efc123 100644
--- a/src/com/android/launcher2/HolographicOutlineHelper.java
+++ b/src/com/android/launcher2/HolographicOutlineHelper.java
@@ -184,7 +184,7 @@ public class HolographicOutlineHelper {
// draw the inner and outer blur
srcDstCanvas.setBitmap(srcDst);
- srcDstCanvas.drawColor(0x00000000, PorterDuff.Mode.CLEAR);
+ srcDstCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
mHolographicPaint.setColor(color);
srcDstCanvas.drawBitmap(thickInnerBlur, thickInnerBlurOffset[0], thickInnerBlurOffset[1],
mHolographicPaint);
diff --git a/src/com/android/launcher2/IconCache.java b/src/com/android/launcher2/IconCache.java
index ae8c98a..468645b 100644
--- a/src/com/android/launcher2/IconCache.java
+++ b/src/com/android/launcher2/IconCache.java
@@ -67,7 +67,7 @@ public class IconCache {
public Drawable getFullResDefaultActivityIcon() {
return getFullResIcon(Resources.getSystem(),
- com.android.internal.R.drawable.sym_def_app_icon);
+ com.android.internal.R.mipmap.sym_def_app_icon);
}
public Drawable getFullResIcon(Resources resources, int iconId) {
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 7faa520..2281c84 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -27,13 +27,13 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
+import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.SearchManager;
import android.app.StatusBarManager;
-import android.app.WallpaperManager;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
@@ -77,7 +77,6 @@ import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.method.TextKeyListener;
import android.util.Log;
-import android.view.Display;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -89,6 +88,7 @@ import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.View.OnLongClickListener;
import android.view.accessibility.AccessibilityEvent;
+import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.InputMethodManager;
import android.widget.Advanceable;
import android.widget.EditText;
@@ -106,6 +106,7 @@ import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -308,7 +309,6 @@ public final class Launcher extends Activity
loadHotseats();
checkForLocaleChange();
- setWallpaperDimension();
setContentView(R.layout.launcher);
mHomeCustomizationDrawer = (TabHost) findViewById(R.id.customization_drawer);
if (mHomeCustomizationDrawer != null) {
@@ -546,18 +546,6 @@ public final class Launcher extends Activity
}
}
- private void setWallpaperDimension() {
- WallpaperManager wpm = (WallpaperManager)getSystemService(WALLPAPER_SERVICE);
-
- Display display = getWindowManager().getDefaultDisplay();
- // TODO: Put back when we decide about scrolling the wallpaper
- // boolean isPortrait = display.getWidth() < display.getHeight();
- // final int width = isPortrait ? display.getWidth() : display.getHeight();
- // final int height = isPortrait ? display.getHeight() : display.getWidth();
- wpm.suggestDesiredDimensions(Math.max(display.getWidth(), display.getHeight()),
- Math.max(display.getWidth(), display.getHeight()));
- }
-
// Note: This doesn't do all the client-id magic that BrowserProvider does
// in Browser. (http://b/2425179)
private Uri getDefaultBrowserUri() {
@@ -1001,6 +989,7 @@ public final class Launcher extends Activity
workspace.setOnLongClickListener(this);
workspace.setDragController(dragController);
workspace.setLauncher(this);
+ workspace.setWallpaperDimension();
deleteZone.setLauncher(this);
deleteZone.setDragController(dragController);
@@ -1325,6 +1314,7 @@ public final class Launcher extends Activity
(System.currentTimeMillis() - mAutoAdvanceSentTime));
}
mHandler.removeMessages(ADVANCE_MSG);
+ mHandler.removeMessages(0); // Remove messages sent using postDelayed()
}
}
}
@@ -1425,8 +1415,10 @@ public final class Launcher extends Activity
}
if (!mWorkspace.isDefaultPageShowing()) {
// on the phone, we don't animate the change to the workspace if all apps is visible
- mWorkspace.moveToDefaultScreen(alreadyOnHome &&
- (LauncherApplication.isScreenXLarge() || mState != State.ALL_APPS));
+ boolean animate = alreadyOnHome &&
+ (LauncherApplication.isScreenXLarge() || mState != State.ALL_APPS);
+ mWorkspace.moveToDefaultScreen(animate);
+ if (!animate) mWorkspace.updateWallpaperOffsetImmediately();
}
showWorkspace(alreadyOnHome);
@@ -1503,6 +1495,9 @@ public final class Launcher extends Activity
} catch (NullPointerException ex) {
Log.w(TAG, "problem while stopping AppWidgetHost during Launcher destruction", ex);
}
+ mAppWidgetHost = null;
+
+ mWidgetsToAdvance.clear();
TextKeyListener.getInstance().release();
@@ -1521,6 +1516,11 @@ public final class Launcher extends Activity
}
unregisterReceiver(mCloseSystemDialogsReceiver);
+
+ ((ViewGroup) mWorkspace.getParent()).removeAllViews();
+ mWorkspace.removeAllViews();
+ mWorkspace = null;
+ mDragController = null;
}
@Override
@@ -1987,6 +1987,7 @@ public final class Launcher extends Activity
for (ItemInfo item: mDesktopItems) {
item.unbind();
}
+ mDesktopItems.clear();
}
/**
@@ -2647,10 +2648,11 @@ public final class Launcher extends Activity
// Set pivotY so that at the starting zoom factor, the view is partially
// visible. Modifying initialHeightFactor changes how much of the view is
// initially showing, and hence the perceived angle from which the view enters.
- final float initialHeightFactor = 0.2f;
if (state == State.ALL_APPS) {
- view.setPivotY((1 + initialHeightFactor) * height);
+ final float initialHeightFactor = 0.165f;
+ view.setPivotY((1 - initialHeightFactor) * height);
} else {
+ final float initialHeightFactor = 0.2f;
view.setPivotY(-initialHeightFactor * height);
}
}
@@ -2663,15 +2665,23 @@ public final class Launcher extends Activity
*/
private void cameraZoomOut(State toState, boolean animated) {
final Resources res = getResources();
- final int duration = res.getInteger(R.integer.config_allAppsZoomInTime);
- final float scale = (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor);
final boolean toAllApps = (toState == State.ALL_APPS);
+
+ final int duration = toAllApps ?
+ res.getInteger(R.integer.config_allAppsZoomInTime) :
+ res.getInteger(R.integer.config_customizeZoomInTime);
+
+ final float scale = toAllApps ?
+ (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor) :
+ (float) res.getInteger(R.integer.config_customizeZoomScaleFactor);
+
final View toView = toAllApps ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
setPivotsForZoom(toView, toState, scale);
if (toAllApps) {
mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
+ toView.setAlpha(0f);
} else {
mWorkspace.shrink(ShrinkState.TOP, animated);
}
@@ -2680,8 +2690,17 @@ public final class Launcher extends Activity
ValueAnimator scaleAnim = ObjectAnimator.ofPropertyValuesHolder(toView,
PropertyValuesHolder.ofFloat("scaleX", scale, 1.0f),
PropertyValuesHolder.ofFloat("scaleY", scale, 1.0f));
+
scaleAnim.setDuration(duration);
+ if (toAllApps) {
+ ObjectAnimator alphaAnim = ObjectAnimator.ofPropertyValuesHolder(toView,
+ PropertyValuesHolder.ofFloat("alpha", 1.0f));
+ alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
+ alphaAnim.setDuration(duration);
+ alphaAnim.start();
+ }
+
scaleAnim.setInterpolator(new Workspace.ZoomOutInterpolator());
scaleAnim.addListener(new AnimatorListenerAdapter() {
@Override
@@ -2690,7 +2709,9 @@ public final class Launcher extends Activity
toView.setTranslationX(0.0f);
toView.setTranslationY(0.0f);
toView.setVisibility(View.VISIBLE);
- toView.setAlpha(1.0f);
+ if (!toAllApps) {
+ toView.setAlpha(1.0f);
+ }
}
@Override
public void onAnimationEnd(Animator animation) {
@@ -2707,7 +2728,7 @@ public final class Launcher extends Activity
hideAndShowToolbarButtons(toState, toolbarShowAnim, toolbarHideAnim);
// toView should appear right at the end of the workspace shrink animation
- final int startDelay = res.getInteger(R.integer.config_workspaceShrinkTime) - duration;
+ final int startDelay = 0;
if (mStateAnimation != null) mStateAnimation.cancel();
mStateAnimation = new AnimatorSet();
@@ -2726,6 +2747,8 @@ public final class Launcher extends Activity
toView.setVisibility(View.VISIBLE);
hideAndShowToolbarButtons(toState, null, null);
}
+ mWorkspace.setVerticalWallpaperOffset(toAllApps ?
+ Workspace.WallpaperVerticalOffset.TOP : Workspace.WallpaperVerticalOffset.BOTTOM);
}
/**
@@ -2740,10 +2763,17 @@ public final class Launcher extends Activity
private void cameraZoomIn(State fromState, boolean animated, boolean springLoaded) {
Resources res = getResources();
- int duration = res.getInteger(R.integer.config_allAppsZoomOutTime);
- float scaleFactor = (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor);
- final View fromView =
- (fromState == State.ALL_APPS) ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
+ final boolean fromAllApps = (fromState == State.ALL_APPS);
+
+ int duration = fromAllApps ?
+ res.getInteger(R.integer.config_allAppsZoomOutTime) :
+ res.getInteger(R.integer.config_customizeZoomOutTime);
+
+ float scaleFactor = fromAllApps ?
+ (float) res.getInteger(R.integer.config_allAppsZoomScaleFactor) :
+ (float) res.getInteger(R.integer.config_customizeZoomScaleFactor);
+
+ final View fromView = fromAllApps ? (View) mAllAppsGrid : mHomeCustomizationDrawer;
mCustomizePagedView.endChoiceMode();
mAllAppsPagedView.endChoiceMode();
@@ -2766,6 +2796,7 @@ public final class Launcher extends Activity
ValueAnimator alphaAnim = ObjectAnimator.ofPropertyValuesHolder(fromView,
PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.0f));
alphaAnim.setDuration(res.getInteger(R.integer.config_allAppsFadeOutTime));
+ alphaAnim.setInterpolator(new DecelerateInterpolator(1.5f));
alphaAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -2792,6 +2823,7 @@ public final class Launcher extends Activity
hideAndShowToolbarButtons(State.WORKSPACE, null, null);
}
}
+ mWorkspace.setVerticalWallpaperOffset(Workspace.WallpaperVerticalOffset.MIDDLE);
}
/**
@@ -2869,6 +2901,8 @@ public final class Launcher extends Activity
toView.setVisibility(View.VISIBLE);
hideAndShowToolbarButtons(toState, null, null);
}
+ mWorkspace.setVerticalWallpaperOffset((toState == State.ALL_APPS) ?
+ Workspace.WallpaperVerticalOffset.TOP : Workspace.WallpaperVerticalOffset.BOTTOM);
}
void showAllApps(boolean animated) {
diff --git a/src/com/android/launcher2/LauncherAppWidgetHost.java b/src/com/android/launcher2/LauncherAppWidgetHost.java
index 46e66e7..68d4903 100644
--- a/src/com/android/launcher2/LauncherAppWidgetHost.java
+++ b/src/com/android/launcher2/LauncherAppWidgetHost.java
@@ -36,4 +36,10 @@ public class LauncherAppWidgetHost extends AppWidgetHost {
AppWidgetProviderInfo appWidget) {
return new LauncherAppWidgetHostView(context);
}
+
+ @Override
+ public void stopListening() {
+ super.stopListening();
+ clearViews();
+ }
}
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 713268a..7e72610 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -492,6 +492,9 @@ public class LauncherModel extends BroadcastReceiver {
mLoaderTask.stopLocked();
}
}
+ mItems.clear();
+ mAppWidgets.clear();
+ mFolders.clear();
}
/**
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index 6c9aac1..bb59678 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -888,6 +888,14 @@ public abstract class PagedView extends ViewGroup {
invalidate();
}
+ protected float maxOverScroll() {
+ // Using the formula in overScroll, assuming that f = 1.0 (which it should generally not
+ // exceed). Used to find out how much extra wallpaper we need for the overscroll effect
+ float f = 1.0f;
+ f = f / (Math.abs(f)) * (overScrollInfluenceCurve(Math.abs(f)));
+ return OVERSCROLL_DAMP_FACTOR * f;
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
// Skip touch handling if there are no pages to swipe
diff --git a/src/com/android/launcher2/PagedViewIcon.java b/src/com/android/launcher2/PagedViewIcon.java
index 6ce308b..0af7b8a 100644
--- a/src/com/android/launcher2/PagedViewIcon.java
+++ b/src/com/android/launcher2/PagedViewIcon.java
@@ -39,7 +39,7 @@ import com.android.launcher.R;
* An icon on a PagedView, specifically for items in the launcher's paged view (with compound
* drawables on the top).
*/
-public class PagedViewIcon extends CacheableTextView implements Checkable {
+public class PagedViewIcon extends CachedTextView implements Checkable {
private static final String TAG = "PagedViewIcon";
// holographic outline
@@ -143,7 +143,6 @@ public class PagedViewIcon extends CacheableTextView implements Checkable {
mIcon = info.iconBitmap;
setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
setText(info.title);
- buildAndEnableCache();
setTag(info);
if (createHolographicOutlines) {
@@ -160,7 +159,6 @@ public class PagedViewIcon extends CacheableTextView implements Checkable {
modelIconCache.getFullResIcon(info, packageManager), mContext);
setCompoundDrawablesWithIntrinsicBounds(null, new FastBitmapDrawable(mIcon), null, null);
setText(info.loadLabel(packageManager));
- buildAndEnableCache();
setTag(info);
if (createHolographicOutlines) {
diff --git a/src/com/android/launcher2/PagedViewWithDraggableItems.java b/src/com/android/launcher2/PagedViewWithDraggableItems.java
index f24d7e0..3f72292 100644
--- a/src/com/android/launcher2/PagedViewWithDraggableItems.java
+++ b/src/com/android/launcher2/PagedViewWithDraggableItems.java
@@ -150,4 +150,10 @@ public abstract class PagedViewWithDraggableItems extends PagedView
public void setDragSlopeThreshold(float dragSlopeThreshold) {
mDragSlopeThreshold = dragSlopeThreshold;
}
+
+ @Override
+ protected void onDetachedFromWindow() {
+ mLastTouchedItem = null;
+ super.onDetachedFromWindow();
+ }
}
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 9fcd1b4..8e0308c 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -203,6 +203,17 @@ public class Workspace extends SmoothPagedView
private final Camera mCamera = new Camera();
private final float mTempFloat2[] = new float[2];
+ enum WallpaperVerticalOffset { TOP, MIDDLE, BOTTOM };
+ int mWallpaperWidth;
+ int mWallpaperHeight;
+ float mTargetHorizontalWallpaperOffset = 0.0f;
+ float mTargetVerticalWallpaperOffset = 0.5f;
+ float mHorizontalWallpaperOffset = 0.0f;
+ float mVerticalWallpaperOffset = 0.5f;
+ long mLastWallpaperOffsetUpdateTime;
+ boolean mWallpaperOffsetDirty;
+ boolean mUpdateWallpaperOffsetImmediately = false;
+
/**
* Used to inflate the Workspace from XML.
*
@@ -387,17 +398,6 @@ public class Workspace extends SmoothPagedView
}
/**
- * Sets the current screen.
- *
- * @param currentPage
- */
- @Override
- void setCurrentPage(int currentPage) {
- super.setCurrentPage(currentPage);
- updateWallpaperOffset(mScrollX);
- }
-
- /**
* Adds the specified child in the specified screen. The position and dimension of
* the child are defined by x, y, spanX and spanY.
*
@@ -558,17 +558,157 @@ public class Workspace extends SmoothPagedView
Launcher.setScreen(mCurrentPage);
};
- private void updateWallpaperOffset(int scrollRange) {
- final boolean isStaticWallpaper = (mWallpaperManager != null) &&
- (mWallpaperManager.getWallpaperInfo() == null);
- if (LauncherApplication.isScreenXLarge() && !isStaticWallpaper) {
- IBinder token = getWindowToken();
- if (token != null) {
- mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 0 );
- mWallpaperManager.setWallpaperOffsets(getWindowToken(),
- Math.max(0.f, Math.min(mScrollX/(float)scrollRange, 1.f)), 0);
- }
+ // As a ratio of screen height, the total distance we want the parallax effect to span
+ // vertically
+ private float wallpaperTravelToScreenHeightRatio(int width, int height) {
+ return 1.1f;
+ }
+
+ // As a ratio of screen height, the total distance we want the parallax effect to span
+ // horizontally
+ private float wallpaperTravelToScreenWidthRatio(int width, int height) {
+ float aspectRatio = width / (float) height;
+
+ // At an aspect ratio of 16/10, the wallpaper parallax effect should span 1.5 * screen width
+ // At an aspect ratio of 10/16, the wallpaper parallax effect should span 1.2 * screen width
+ // We will use these two data points to extrapolate how much the wallpaper parallax effect
+ // to span (ie travel) at any aspect ratio:
+
+ final float ASPECT_RATIO_LANDSCAPE = 16/10f;
+ final float ASPECT_RATIO_PORTRAIT = 10/16f;
+ final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE = 1.5f;
+ final float WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT = 1.2f;
+
+ // To find out the desired width at different aspect ratios, we use the following two
+ // formulas, where the coefficient on x is the aspect ratio (width/height):
+ // (16/10)x + y = 1.5
+ // (10/16)x + y = 1.2
+ // We solve for x and y and end up with a final formula:
+ final float x =
+ (WALLPAPER_WIDTH_TO_SCREEN_RATIO_LANDSCAPE - WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT) /
+ (ASPECT_RATIO_LANDSCAPE - ASPECT_RATIO_PORTRAIT);
+ final float y = WALLPAPER_WIDTH_TO_SCREEN_RATIO_PORTRAIT - x * ASPECT_RATIO_PORTRAIT;
+ return x * aspectRatio + y;
+ }
+
+ // The range of scroll values for Workspace
+ private int getScrollRange() {
+ return getChildOffset(getChildCount() - 1) - getChildOffset(0);
+ }
+
+ protected void setWallpaperDimension() {
+ WallpaperManager wpm =
+ (WallpaperManager) mLauncher.getSystemService(Context.WALLPAPER_SERVICE);
+
+ Display display = mLauncher.getWindowManager().getDefaultDisplay();
+ final int maxDim = Math.max(display.getWidth(), display.getHeight());
+ final int minDim = Math.min(display.getWidth(), display.getHeight());
+
+ // We need to ensure that there is enough extra space in the wallpaper for the intended
+ // parallax effects
+ mWallpaperWidth = (int) (maxDim * wallpaperTravelToScreenWidthRatio(maxDim, minDim));
+ mWallpaperHeight = (int)(maxDim * wallpaperTravelToScreenHeightRatio(maxDim, minDim));
+ wpm.suggestDesiredDimensions(mWallpaperWidth, mWallpaperHeight);
+ }
+
+ public void setVerticalWallpaperOffset(WallpaperVerticalOffset offsetPosition) {
+ float offset = 0.5f;
+ Display display = mLauncher.getWindowManager().getDefaultDisplay();
+ int wallpaperTravelHeight = (int) (display.getHeight() *
+ wallpaperTravelToScreenHeightRatio(display.getWidth(), display.getHeight()));
+ float offsetFromCenter = (wallpaperTravelHeight / (float) mWallpaperHeight) / 2f;
+ switch (offsetPosition) {
+ case TOP:
+ offset = 0.5f - offsetFromCenter;
+ break;
+ case MIDDLE:
+ offset = 0.5f;
+ break;
+ case BOTTOM:
+ offset = 0.5f + offsetFromCenter;
+ break;
+ }
+ mTargetVerticalWallpaperOffset = offset;
+ mWallpaperOffsetDirty = true;
+ }
+
+ private void updateHorizontalWallpaperOffset() {
+ if (LauncherApplication.isScreenXLarge()) {
+ Display display = mLauncher.getWindowManager().getDefaultDisplay();
+ // The wallpaper travel width is how far, from left to right, the wallpaper will move
+ // at this orientation (for example, in portrait mode we don't move all the way to the
+ // edges of the wallpaper, or otherwise the parallax effect would be too strong)
+ int wallpaperTravelWidth = (int) (display.getWidth() *
+ wallpaperTravelToScreenWidthRatio(display.getWidth(), display.getHeight()));
+
+ // Account for overscroll: you only see the absolute edge of the wallpaper if
+ // you overscroll as far as you can in landscape mode
+ int overscrollOffset = (int) (maxOverScroll() * display.getWidth());
+ float overscrollRatio = overscrollOffset / (float) getScrollRange();
+ int scrollRangeWithOverscroll = getScrollRange() + 2 * overscrollOffset;
+
+ // Set wallpaper offset steps (1 / (number of screens - 1))
+ // We have 3 vertical offset states (centered, and then top/bottom aligned
+ // for all apps/customize)
+ mWallpaperManager.setWallpaperOffsetSteps(1.0f / (getChildCount() - 1), 1.0f / (3 - 1));
+
+ float scrollProgress =
+ mScrollX / (float) scrollRangeWithOverscroll + overscrollRatio;
+ float offsetInDips = wallpaperTravelWidth * scrollProgress +
+ (mWallpaperWidth - wallpaperTravelWidth) / 2;
+ float offset = offsetInDips / (float) mWallpaperWidth;
+
+ mTargetHorizontalWallpaperOffset = Math.max(0f, Math.min(offset, 1.0f));
+ mWallpaperOffsetDirty = true;
+ }
+ }
+
+ public void updateWallpaperOffsetImmediately() {
+ mUpdateWallpaperOffsetImmediately = true;
+ }
+
+ private void updateWallpaperOffsets(boolean immediate) {
+ long currentTime = System.currentTimeMillis();
+ long millisecondsSinceLastUpdate = currentTime - mLastWallpaperOffsetUpdateTime;
+ millisecondsSinceLastUpdate = Math.min((long) (1000/30f), millisecondsSinceLastUpdate);
+ millisecondsSinceLastUpdate = Math.min(1L, millisecondsSinceLastUpdate);
+ final float PERCENT_TO_CATCH_UP_IN_100_MS_HORIZONTAL = 25f;
+ final float PERCENT_TO_CATCH_UP_IN_100_MS_VERTICAL = 25f;
+ final float UPDATE_THRESHOLD = 0.0001f;
+ float hOffsetDelta = mTargetHorizontalWallpaperOffset - mHorizontalWallpaperOffset;
+ float vOffsetDelta = mTargetVerticalWallpaperOffset - mVerticalWallpaperOffset;
+ boolean stopUpdating =
+ Math.abs(hOffsetDelta / mTargetHorizontalWallpaperOffset) < UPDATE_THRESHOLD &&
+ Math.abs(vOffsetDelta / mTargetVerticalWallpaperOffset) < UPDATE_THRESHOLD;
+
+ if (stopUpdating || immediate) {
+ mHorizontalWallpaperOffset = mTargetHorizontalWallpaperOffset;
+ mVerticalWallpaperOffset = mTargetVerticalWallpaperOffset;
+ } else {
+ float percentToCatchUpVertical =
+ millisecondsSinceLastUpdate / 100f * PERCENT_TO_CATCH_UP_IN_100_MS_VERTICAL;
+ float percentToCatchUpHorizontal =
+ millisecondsSinceLastUpdate / 100f * PERCENT_TO_CATCH_UP_IN_100_MS_HORIZONTAL;
+ mHorizontalWallpaperOffset += percentToCatchUpHorizontal * hOffsetDelta;
+ mVerticalWallpaperOffset +=
+ percentToCatchUpVertical * (mTargetVerticalWallpaperOffset - mVerticalWallpaperOffset);
+ }
+ IBinder token = getWindowToken();
+ if (token != null) {
+ mWallpaperManager.setWallpaperOffsets(getWindowToken(),
+ mHorizontalWallpaperOffset, mVerticalWallpaperOffset);
}
+ if (!stopUpdating && !immediate) {
+ invalidate();
+ mWallpaperOffsetDirty = true;
+ }
+ mLastWallpaperOffsetUpdateTime = System.currentTimeMillis();
+ }
+
+ @Override
+ public void computeScroll() {
+ super.computeScroll();
+ updateHorizontalWallpaperOffset();
}
public void showOutlines() {
@@ -737,6 +877,9 @@ public class Workspace extends SmoothPagedView
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ if (mFirstLayout && mCurrentPage >= 0 && mCurrentPage < getChildCount()) {
+ mUpdateWallpaperOffsetImmediately = true;
+ }
super.onLayout(changed, left, top, right, bottom);
// if shrinkToBottom() is called on initialization, it has to be deferred
@@ -777,12 +920,15 @@ public class Workspace extends SmoothPagedView
@Override
protected void onDraw(Canvas canvas) {
+ if (mWallpaperOffsetDirty) {
+ updateWallpaperOffsets(mUpdateWallpaperOffsetImmediately);
+ mWallpaperOffsetDirty = false;
+ mUpdateWallpaperOffsetImmediately = false;
+ }
+
// Draw the background gradient if necessary
if (mBackground != null && mBackgroundAlpha > 0.0f) {
int alpha = (int) (mBackgroundAlpha * 255);
- mBackground.setAlpha(alpha);
- mBackground.setBounds(mScrollX, 0, mScrollX + getMeasuredWidth(), getMeasuredHeight());
- mBackground.draw(canvas);
if (mDrawCustomizeTrayBackground) {
// Find out where to offset the gradient for the customization tray content
mCustomizationDrawer.getLocationOnScreen(mCustomizationDrawerPos);
@@ -800,9 +946,15 @@ public class Workspace extends SmoothPagedView
// Draw the bg gradient
final int offset = (int) (mCustomizationDrawerPos[1] +
mCustomizationDrawerTransformedPos[1]);
+ mBackground.setAlpha(alpha);
mBackground.setBounds(mScrollX, offset, mScrollX + getMeasuredWidth(),
offset + getMeasuredHeight());
mBackground.draw(canvas);
+ } else {
+ mBackground.setAlpha(alpha);
+ mBackground.setBounds(mScrollX, 0, mScrollX + getMeasuredWidth(),
+ getMeasuredHeight());
+ mBackground.draw(canvas);
}
}
super.onDraw(canvas);
@@ -1031,6 +1183,7 @@ public class Workspace extends SmoothPagedView
getResources().getDimension(R.dimen.allAppsSmallScreenVerticalMarginLandscape));
float finalAlpha = 1.0f;
float extraShrinkFactor = 1.0f;
+
if (shrinkState == ShrinkState.BOTTOM_VISIBLE) {
newY = screenHeight - newY - scaledPageHeight;
} else if (shrinkState == ShrinkState.BOTTOM_HIDDEN) {
@@ -1048,6 +1201,13 @@ public class Workspace extends SmoothPagedView
getResources().getDimension(R.dimen.customizeSmallScreenVerticalMarginLandscape));
}
+ int duration;
+ if (shrinkState == ShrinkState.BOTTOM_HIDDEN || shrinkState == ShrinkState.BOTTOM_VISIBLE) {
+ duration = res.getInteger(R.integer.config_allAppsWorkspaceShrinkTime);
+ } else {
+ duration = res.getInteger(R.integer.config_customizeWorkspaceShrinkTime);
+ }
+
// We animate all the screens to the centered position in workspace
// At the same time, the screens become greyed/dimmed
@@ -1062,17 +1222,16 @@ public class Workspace extends SmoothPagedView
if (mAnimator != null) {
mAnimator.cancel();
}
+
mAnimator = new AnimatorSet();
for (int i = 0; i < screenCount; i++) {
- CellLayout cl = (CellLayout) getChildAt(i);
+ final CellLayout cl = (CellLayout) getChildAt(i);
float rotation = (-i + 2) * WORKSPACE_ROTATION;
float rotationScaleX = (float) (1.0f / Math.cos(Math.PI * rotation / 180.0f));
float rotationScaleY = getYScaleForScreen(i);
if (animated) {
- final int duration = res.getInteger(R.integer.config_workspaceShrinkTime);
-
ObjectAnimator animWithInterpolator = ObjectAnimator.ofPropertyValuesHolder(cl,
PropertyValuesHolder.ofFloat("x", newX),
PropertyValuesHolder.ofFloat("y", newY),