Merge "Fix a monkey crash"
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java
index 12fe971..8a4bdc7 100644
--- a/src/com/android/launcher2/AppsCustomizePagedView.java
+++ b/src/com/android/launcher2/AppsCustomizePagedView.java
@@ -385,37 +385,12 @@
protected void determineDraggingStart(android.view.MotionEvent ev) {
// Disable dragging by pulling an app down for now.
}
+
private void beginDraggingApplication(View v) {
- // Make a copy of the ApplicationInfo
- ApplicationInfo appInfo = new ApplicationInfo((ApplicationInfo) v.getTag());
-
- // Compose the drag image (top compound drawable, index is 1)
- final TextView tv = (TextView) v;
- final Drawable icon = tv.getCompoundDrawables()[1];
- Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(),
- Bitmap.Config.ARGB_8888);
- mCanvas.setBitmap(b);
- mCanvas.save();
- mCanvas.translate((v.getWidth() - icon.getIntrinsicWidth()) / 2, v.getPaddingTop());
- icon.draw(mCanvas);
- mCanvas.restore();
-
- // Compose the visible rect of the drag image
- Rect dragRect = null;
- if (v instanceof TextView) {
- int top = v.getPaddingTop();
- int left = (b.getWidth() - mAppIconSize) / 2;
- int right = left + mAppIconSize;
- int bottom = top + mAppIconSize;
- dragRect = new Rect(left, top, right, bottom);
- }
-
- // Start the drag
- mLauncher.lockScreenOrientation();
- mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b);
- mDragController.startDrag(v, b, this, appInfo, DragController.DRAG_ACTION_COPY, dragRect);
- b.recycle();
+ mLauncher.getWorkspace().onDragStartedWithItem(v);
+ mLauncher.getWorkspace().beginDragShared(v, this);
}
+
private void beginDraggingWidget(View v) {
// Get the widget preview as the drag representation
ImageView image = (ImageView) v.findViewById(R.id.widget_preview);
diff --git a/src/com/android/launcher2/BubbleTextView.java b/src/com/android/launcher2/BubbleTextView.java
index 8c0c27c..57a6584 100644
--- a/src/com/android/launcher2/BubbleTextView.java
+++ b/src/com/android/launcher2/BubbleTextView.java
@@ -56,7 +56,6 @@
private final HolographicOutlineHelper mOutlineHelper = new HolographicOutlineHelper();
private final Canvas mTempCanvas = new Canvas();
private final Rect mTempRect = new Rect();
- private final Paint mTempPaint = new Paint();
private boolean mDidInvalidateForPressedState;
private Bitmap mPressedOrFocusedBackground;
private int mFocusedOutlineColor;
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index 0bdfec1..37abe5a 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -26,6 +26,7 @@
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
@@ -34,6 +35,7 @@
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
+import android.widget.TextView;
import com.android.launcher.R;
@@ -167,12 +169,13 @@
return mDragController.onTouchEvent(ev);
}
- public void getDescendantRectRelativeToSelf(View descendant, Rect r) {
+ public float getDescendantRectRelativeToSelf(View descendant, Rect r) {
mTmpXY[0] = 0;
mTmpXY[1] = 0;
- getDescendantCoordRelativeToSelf(descendant, mTmpXY);
+ float scale = getDescendantCoordRelativeToSelf(descendant, mTmpXY);
r.set(mTmpXY[0], mTmpXY[1],
mTmpXY[0] + descendant.getWidth(), mTmpXY[1] + descendant.getHeight());
+ return scale;
}
private float getDescendantCoordRelativeToSelf(View descendant, int[] coord) {
@@ -315,6 +318,7 @@
public void animateViewIntoPosition(DragView dragView, final View child) {
animateViewIntoPosition(dragView, child, null);
}
+
public void animateViewIntoPosition(DragView dragView, final View child,
final Runnable onFinishAnimationRunnable) {
((CellLayoutChildren) child.getParent()).measureChild(child);
@@ -324,18 +328,30 @@
getViewRectRelativeToSelf(dragView, r);
int coord[] = new int[2];
- coord[0] = lp.x + (lp.width / 2);
- coord[1] = lp.y + (lp.height / 2);
+ coord[0] = lp.x;
+ coord[1] = lp.y;
// Since the child hasn't necessarily been laid out, we force the lp to be updated with
- // the correct coordinates and use these to determine the final location
+ // the correct coordinates (above) and use these to determine the final location
float scale = getDescendantCoordRelativeToSelf((View) child.getParent(), coord);
- int toX = coord[0] - lp.width / 2;
- int toY = coord[1] - lp.height / 2;
- toX -= (dragView.getWidth() - child.getMeasuredWidth()) / 2;
- toY -= (dragView.getHeight() - child.getMeasuredHeight()) / 2;
+ int toX = coord[0];
+ int toY = coord[1];
+ if (child instanceof TextView) {
+ TextView tv = (TextView) child;
+ Drawable d = tv.getCompoundDrawables()[1];
- final int fromX = r.left + (dragView.getWidth() - child.getMeasuredWidth()) / 2;
- final int fromY = r.top + (dragView.getHeight() - child.getMeasuredHeight()) / 2;
+ // Center in the y coordinate about the target's drawable
+ toY += Math.round(scale * tv.getPaddingTop());
+ toY -= (dragView.getHeight() - (int) Math.round(scale * d.getIntrinsicHeight())) / 2;
+ // Center in the x coordinate about the target's drawable
+ toX -= (dragView.getMeasuredWidth() - Math.round(scale * child.getMeasuredWidth())) / 2;
+ } else {
+ toY -= (Math.round(scale * (dragView.getHeight() - child.getMeasuredHeight()))) / 2;
+ toX -= (Math.round(scale * (dragView.getMeasuredWidth()
+ - child.getMeasuredWidth()))) / 2;
+ }
+
+ final int fromX = r.left;
+ final int fromY = r.top;
child.setVisibility(INVISIBLE);
child.setAlpha(0);
Runnable onCompleteRunnable = new Runnable() {
@@ -400,6 +416,10 @@
mDropAnim.cancel();
}
+ if (mFadeOutAnim != null) {
+ mFadeOutAnim.cancel();
+ }
+
mDropView = view;
final float initialAlpha = view.getAlpha();
mDropAnim = new ValueAnimator();
@@ -424,8 +444,8 @@
float motionPercent = motionInterpolator == null ? percent :
motionInterpolator.getInterpolation(percent);
- mDropViewPos[0] = from.left + (int) ((to.left - from.left) * motionPercent);
- mDropViewPos[1] = from.top + (int) ((to.top - from.top) * motionPercent);
+ mDropViewPos[0] = from.left + (int) Math.round(((to.left - from.left) * motionPercent));
+ mDropViewPos[1] = from.top + (int) Math.round(((to.top - from.top) * motionPercent));
mDropViewScale = percent * finalScale + (1 - percent);
mDropViewAlpha = alphaPercent * finalAlpha + (1 - alphaPercent) * initialAlpha;
invalidate(mDropViewPos[0], mDropViewPos[1],
diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java
index 78df80f..dd0bffd 100644
--- a/src/com/android/launcher2/Folder.java
+++ b/src/com/android/launcher2/Folder.java
@@ -90,6 +90,7 @@
private int[] mTargetCell = new int[2];
private int[] mPreviousTargetCell = new int[2];
private int[] mEmptyCell = new int[2];
+ private int[] mTempXY = new int[2];
private Alarm mReorderAlarm = new Alarm();
private Alarm mOnExitAlarm = new Alarm();
private TextView mFolderName;
@@ -205,14 +206,13 @@
}
mLauncher.getWorkspace().onDragStartedWithItem(v);
- mDragController.startDrag(v, this, item, DragController.DRAG_ACTION_COPY);
+ mLauncher.getWorkspace().beginDragShared(v, this);
mIconDrawable = ((TextView) v).getCompoundDrawables()[1];
mCurrentDragInfo = item;
mEmptyCell[0] = item.cellX;
mEmptyCell[1] = item.cellY;
mCurrentDragView = v;
-
}
return true;
}
@@ -270,18 +270,6 @@
return true;
}
- public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
- if (!view.isInTouchMode()) {
- return false;
- }
-
- ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position);
-
- mDragController.startDrag(view, this, app, DragController.DRAG_ACTION_COPY);
- mLauncher.closeFolder(this);
- return true;
- }
-
public void setDragController(DragController dragController) {
mDragController = dragController;
}
diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java
index 952916d..93f56fb 100644
--- a/src/com/android/launcher2/FolderIcon.java
+++ b/src/com/android/launcher2/FolderIcon.java
@@ -24,6 +24,7 @@
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Color;
+import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -286,12 +287,13 @@
public void performCreateAnimation(final ShortcutInfo destInfo, final View destView,
final ShortcutInfo srcInfo, final View srcView, Rect dstRect,
- Runnable postAnimationRunnable) {
+ float scaleRelativeToDragLayer, Runnable postAnimationRunnable) {
Drawable animateDrawable = ((TextView) destView).getCompoundDrawables()[1];
computePreviewDrawingParams(animateDrawable.getIntrinsicWidth(), destView.getMeasuredWidth());
+
// This will animate the dragView (srcView) into the new folder
- onDrop(srcInfo, srcView, dstRect, 1, postAnimationRunnable);
+ onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, postAnimationRunnable);
// This will animate the first item from it's position as an icon into its
// position as the first item in the preview
@@ -309,8 +311,8 @@
mFolderRingAnimator.animateToNaturalState();
}
- private void onDrop(final ShortcutInfo item, View animateView, Rect finalRect, int index,
- Runnable postAnimationRunnable) {
+ private void onDrop(final ShortcutInfo item, View animateView, Rect finalRect,
+ float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable) {
item.cellX = -1;
item.cellY = -1;
DragLayer dragLayer = mLauncher.getDragLayer();
@@ -319,22 +321,22 @@
Rect to = finalRect;
if (to == null) {
to = new Rect();
- dragLayer.getDescendantRectRelativeToSelf(this, to);
+ scaleRelativeToDragLayer = dragLayer.getDescendantRectRelativeToSelf(this, to);
}
- if (animateView.getMeasuredWidth() != to.width() ||
- animateView.getMeasuredHeight() != to.height()) {
- int offsetX = (animateView.getMeasuredWidth() - to.width()) / 2;
- int offsetY = (animateView.getMeasuredHeight() - to.height()) / 2;
- to.offset(-offsetX, -offsetY);
- }
- float scale = adjustFinalScreenRectForIndex(to, index);
+ int[] center = new int[2];
+ float scale = getLocalCenterForIndex(index, center);
+ center[0] = (int) Math.round(scaleRelativeToDragLayer * center[0]);
+ center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]);
+
+ to.offset(center[0] - animateView.getMeasuredWidth() / 2,
+ center[1] - animateView.getMeasuredHeight() / 2);
float finalAlpha = index < NUM_ITEMS_IN_PREVIEW ? 0.5f : 0f;
- dragLayer.animateView(animateView, from, to, finalAlpha, scale, DROP_IN_ANIMATION_DURATION,
- new DecelerateInterpolator(2), new AccelerateInterpolator(2), postAnimationRunnable,
- false);
+ dragLayer.animateView(animateView, from, to, finalAlpha, scale * scaleRelativeToDragLayer,
+ DROP_IN_ANIMATION_DURATION, new DecelerateInterpolator(2),
+ new AccelerateInterpolator(2), postAnimationRunnable, false);
postDelayed(new Runnable() {
public void run() {
addItem(item);
@@ -350,7 +352,7 @@
} else {
item = (ShortcutInfo) d.dragInfo;
}
- onDrop(item, d.dragView, null, mInfo.contents.size(), d.postAnimationRunnable);
+ onDrop(item, d.dragView, null, 1.0f, mInfo.contents.size(), d.postAnimationRunnable);
}
public DropTarget getDropTargetDelegate(DragObject d) {
@@ -398,15 +400,16 @@
Drawable drawable;
}
- private float adjustFinalScreenRectForIndex(Rect r, int index) {
+ private float getLocalCenterForIndex(int index, int[] center) {
mParams = computePreviewItemDrawingParams(Math.min(NUM_ITEMS_IN_PREVIEW, index), mParams);
mParams.transX += mPreviewOffsetX;
mParams.transY += mPreviewOffsetY;
- float offsetX = mParams.transX + (mParams.scale * mIntrinsicIconSize) / 2 - mTotalWidth / 2;
- float offsetY = mParams.transY + (mParams.scale * mIntrinsicIconSize) / 2 - mTotalWidth / 2;
+ float offsetX = mParams.transX + (mParams.scale * mIntrinsicIconSize) / 2;
+ float offsetY = mParams.transY + (mParams.scale * mIntrinsicIconSize) / 2;
- r.offset((int) offsetX, (int) offsetY);
+ center[0] = (int) Math.round(offsetX);
+ center[1] = (int) Math.round(offsetY);
return mParams.scale;
}
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 885d360..b26e3ac 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -94,7 +94,7 @@
import com.android.common.Search;
import com.android.launcher.R;
-import com.android.launcher2.Workspace.ShrinkState;
+import com.android.launcher2.Workspace.State;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -845,7 +845,7 @@
mWorkspace.setHapticFeedbackEnabled(false);
mWorkspace.setOnLongClickListener(this);
mWorkspace.setup(this, dragController);
- mWorkspace.setWallpaperDimension();
+ dragController.addDragListener(mWorkspace);
// Get the search/delete bar
mSearchDeleteBar = (SearchDropTargetBar) mDragLayer.findViewById(R.id.qsb_bar);
@@ -2341,19 +2341,8 @@
setPivotsForZoom(toView, toState, scale);
-
- if (springLoaded) {
- if (toState == State.APPS_CUSTOMIZE) {
- // Shrink workspaces away if going back to AppsCustomize from spring loaded mode
- mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
- } else {
- // Shrink workspaces to bottom if going back to AllApps from spring loaded mode
- mWorkspace.shrink(ShrinkState.BOTTOM_VISIBLE, animated);
- }
- } else {
- // Shrink workspaces away if going to AllApps/AppsCustomize from workspace
- mWorkspace.shrink(ShrinkState.BOTTOM_HIDDEN, animated);
- }
+ // Shrink workspaces away if going to AppsCustomize from workspace
+ mWorkspace.shrink(Workspace.State.SMALL, animated);
if (animated) {
final ValueAnimator scaleAnim = ValueAnimator.ofFloat(0f, 1f).setDuration(duration);
@@ -2563,7 +2552,7 @@
}
void exitSpringLoadedDragMode() {
if (mState == State.APPS_CUSTOMIZE_SPRING_LOADED) {
- mWorkspace.exitSpringLoadedDragMode(Workspace.ShrinkState.BOTTOM_VISIBLE);
+ mWorkspace.exitSpringLoadedDragMode(Workspace.State.SMALL);
cameraZoomOut(State.APPS_CUSTOMIZE, true, true);
mState = State.APPS_CUSTOMIZE;
}
diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java
index e5e7a20..9ef1fa8 100644
--- a/src/com/android/launcher2/PagedView.java
+++ b/src/com/android/launcher2/PagedView.java
@@ -301,13 +301,17 @@
}
protected void pageBeginMoving() {
- mIsPageMoving = true;
- onPageBeginMoving();
+ if (!mIsPageMoving) {
+ mIsPageMoving = true;
+ onPageBeginMoving();
+ }
}
protected void pageEndMoving() {
- onPageEndMoving();
- mIsPageMoving = false;
+ if (mIsPageMoving) {
+ mIsPageMoving = false;
+ onPageEndMoving();
+ }
}
protected boolean isPageMoving() {
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 87279d0..701b33b 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -39,6 +39,7 @@
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
@@ -74,7 +75,8 @@
* interact with. A workspace is meant to be used with a fixed width only.
*/
public class Workspace extends SmoothPagedView
- implements DropTarget, DragSource, DragScroller, View.OnTouchListener {
+ implements DropTarget, DragSource, DragScroller, View.OnTouchListener,
+ DragController.DragListener {
@SuppressWarnings({"UnusedDeclaration"})
private static final String TAG = "Launcher.Workspace";
@@ -151,15 +153,21 @@
// State variable that indicates whether the pages are small (ie when you're
// in all apps or customize mode)
- private boolean mIsSmall = false;
- private boolean mIsInUnshrinkAnimation = false;
+
+ enum State { NORMAL, SPRING_LOADED, SMALL };
+ private State mState;
+ private boolean mIsSwitchingState = false;
+
+ private boolean mSwitchStateAfterFirstLayout = false;
+ private State mStateAfterFirstLayout;
+
+ private AnimatorSet mAnimator;
private AnimatorListener mShrinkAnimationListener;
private AnimatorListener mUnshrinkAnimationListener;
- enum ShrinkState { SPRING_LOADED, MIDDLE, BOTTOM_HIDDEN, BOTTOM_VISIBLE };
- private ShrinkState mShrinkState;
- private boolean mWaitingToShrink = false;
- private ShrinkState mWaitingToShrinkState;
- private AnimatorSet mAnimator;
+
+ boolean mAnimatingViewIntoPlace = false;
+ boolean mIsDragOccuring = false;
+ boolean mChildrenLayersEnabled = true;
/** Is the user is dragging an item near the edge of a page? */
private boolean mInScrollArea = false;
@@ -277,6 +285,16 @@
setMotionEventSplittingEnabled(true);
}
+ public void onDragStart(DragSource source, Object info, int dragAction) {
+ mIsDragOccuring = true;
+ updateChildrenLayersEnabled();
+ }
+
+ public void onDragEnd() {
+ mIsDragOccuring = false;
+ updateChildrenLayersEnabled();
+ }
+
/**
* Initializes various states for this workspace.
*/
@@ -299,25 +317,26 @@
mUnshrinkAnimationListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- mIsInUnshrinkAnimation = true;
+ mIsSwitchingState = true;
}
@Override
public void onAnimationEnd(Animator animation) {
- mIsInUnshrinkAnimation = false;
+ mIsSwitchingState = false;
mSyncWallpaperOffsetWithScroll = true;
mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
mAnimator = null;
- enableChildrenLayers(false);
+ updateChildrenLayersEnabled();
}
};
mShrinkAnimationListener = new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
- enableChildrenLayers(true);
+ mIsSwitchingState = true;
}
@Override
public void onAnimationEnd(Animator animation) {
+ mIsSwitchingState = false;
mWallpaperOffset.setOverrideHorizontalCatchupConstant(false);
mAnimator = null;
}
@@ -501,7 +520,7 @@
*/
@Override
public boolean onTouch(View v, MotionEvent event) {
- return (mIsSmall || mIsInUnshrinkAnimation);
+ return (isSmall() || mIsSwitchingState);
}
protected void onWindowVisibilityChanged (int visibility) {
@@ -510,7 +529,7 @@
@Override
public boolean dispatchUnhandledMove(View focused, int direction) {
- if (mIsSmall || mIsInUnshrinkAnimation) {
+ if (isSmall() || mIsSwitchingState) {
// when the home screens are shrunken, shouldn't allow side-scrolling
return false;
}
@@ -529,7 +548,7 @@
@Override
protected void determineScrollingStart(MotionEvent ev) {
- if (!mIsSmall && !mIsInUnshrinkAnimation) {
+ if (!isSmall() && !mIsSwitchingState) {
float deltaX = Math.abs(ev.getX() - mXDown);
float deltaY = Math.abs(ev.getY() - mYDown);
@@ -563,19 +582,23 @@
@Override
protected boolean isScrollingIndicatorEnabled() {
- return mShrinkState != ShrinkState.SPRING_LOADED;
+ return mState != State.SPRING_LOADED;
}
protected void onPageBeginMoving() {
super.onPageBeginMoving();
- if (mNextPage != INVALID_PAGE) {
- // we're snapping to a particular screen
- enableChildrenCache(mCurrentPage, mNextPage);
+ if (isHardwareAccelerated()) {
+ updateChildrenLayersEnabled();
} else {
- // this is when user is actively dragging a particular screen, they might
- // swipe it either left or right (but we won't advance by more than one screen)
- enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
+ if (mNextPage != INVALID_PAGE) {
+ // we're snapping to a particular screen
+ enableChildrenCache(mCurrentPage, mNextPage);
+ } else {
+ // this is when user is actively dragging a particular screen, they might
+ // swipe it either left or right (but we won't advance by more than one screen)
+ enableChildrenCache(mCurrentPage - 1, mCurrentPage + 1);
+ }
}
// Only show page outlines as we pan if we are on large screen
@@ -587,7 +610,12 @@
protected void onPageEndMoving() {
super.onPageEndMoving();
- clearChildrenCache();
+ if (isHardwareAccelerated()) {
+ updateChildrenLayersEnabled();
+ } else {
+ clearChildrenCache();
+ }
+
// Hide the outlines, as long as we're not dragging
if (!mDragController.dragging()) {
// Only hide page outlines as we pan if we are on large screen
@@ -868,7 +896,7 @@
}
void showOutlines() {
- if (!mIsSmall && !mIsInUnshrinkAnimation) {
+ if (!isSmall() && !mIsSwitchingState) {
if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
mChildrenOutlineFadeInAnimation = ObjectAnimator.ofFloat(this, "childrenOutlineAlpha", 1.0f);
@@ -878,7 +906,7 @@
}
void hideOutlines() {
- if (!mIsSmall && !mIsInUnshrinkAnimation) {
+ if (!isSmall() && !mIsSwitchingState) {
if (mChildrenOutlineFadeInAnimation != null) mChildrenOutlineFadeInAnimation.cancel();
if (mChildrenOutlineFadeOutAnimation != null) mChildrenOutlineFadeOutAnimation.cancel();
mChildrenOutlineFadeOutAnimation = ObjectAnimator.ofFloat(this, "childrenOutlineAlpha", 0.0f);
@@ -1070,13 +1098,13 @@
// if shrinkToBottom() is called on initialization, it has to be deferred
// until after the first call to onLayout so that it has the correct width
- if (mWaitingToShrink) {
+ if (mSwitchStateAfterFirstLayout) {
+ mSwitchStateAfterFirstLayout = false;
// shrink can trigger a synchronous onLayout call, so we
// post this to avoid a stack overflow / tangled onLayout calls
post(new Runnable() {
public void run() {
- shrink(mWaitingToShrinkState, false);
- mWaitingToShrink = false;
+ shrink(mStateAfterFirstLayout, false);
}
});
}
@@ -1140,7 +1168,7 @@
@Override
public int getDescendantFocusability() {
- if (mIsSmall) {
+ if (isSmall()) {
return ViewGroup.FOCUS_BLOCK_DESCENDANTS;
}
return super.getDescendantFocusability();
@@ -1158,6 +1186,10 @@
}
}
+ public boolean isSmall() {
+ return mState == State.SMALL;
+ }
+
void enableChildrenCache(int fromPage, int toPage) {
if (fromPage > toPage) {
final int temp = fromPage;
@@ -1185,23 +1217,24 @@
}
}
- protected void enableChildrenLayers(boolean enable) {
- for (int i = 0; i < getPageCount(); i++) {
- ((ViewGroup)getChildAt(i)).setChildrenLayersEnabled(enable);
- }
- }
- @Override
- protected void pageBeginMoving() {
- enableChildrenLayers(true);
- super.pageBeginMoving();
+ private boolean childLayersEnabled() {
+ boolean isSmallOrSpringloaded =
+ isSmall() || mIsSwitchingState || mState == State.SPRING_LOADED;
+ return isSmallOrSpringloaded || isPageMoving() || mIsDragOccuring;
}
- @Override
- protected void pageEndMoving() {
- if (!mIsSmall && !mIsInUnshrinkAnimation) {
- enableChildrenLayers(false);
+ private void updateChildrenLayersEnabled() {
+ boolean small =
+ isSmall() || mIsSwitchingState || mState == State.SPRING_LOADED;
+ boolean dragging = mAnimatingViewIntoPlace || mIsDragOccuring;
+ boolean enableChildrenLayers = small || dragging || isPageMoving();
+
+ if (enableChildrenLayers != mChildrenLayersEnabled) {
+ mChildrenLayersEnabled = enableChildrenLayers;
+ for (int i = 0; i < getPageCount(); i++) {
+ ((ViewGroup)getChildAt(i)).setChildrenLayersEnabled(enableChildrenLayers);
+ }
}
- super.pageEndMoving();
}
@Override
@@ -1219,10 +1252,6 @@
position[0], position[1], 0, null);
}
- public boolean isSmall() {
- return mIsSmall;
- }
-
private float getYScaleForScreen(int screen) {
int x = Math.abs(screen - 2);
@@ -1235,21 +1264,22 @@
return 1.0f;
}
- public void shrink(ShrinkState shrinkState) {
+ public void shrink(State shrinkState) {
shrink(shrinkState, true);
}
// we use this to shrink the workspace for the all apps view and the customize view
- public void shrink(ShrinkState shrinkState, boolean animated) {
+ public void shrink(State shrinkState, boolean animated) {
if (mFirstLayout) {
// (mFirstLayout == "first layout has not happened yet")
// if we get a call to shrink() as part of our initialization (for example, if
// Launcher is started in All Apps mode) then we need to wait for a layout call
// to get our width so we can layout the mini-screen views correctly
- mWaitingToShrink = true;
- mWaitingToShrinkState = shrinkState;
+ mSwitchStateAfterFirstLayout = true;
+ mStateAfterFirstLayout = shrinkState;
return;
}
+
// Stop any scrolling, move to the current page right away
setCurrentPage((mNextPage != INVALID_PAGE) ? mNextPage : mCurrentPage);
@@ -1264,8 +1294,8 @@
}
currentPage.setBackgroundAlphaMultiplier(1.0f);
- mIsSmall = true;
- mShrinkState = shrinkState;
+ mState = shrinkState;
+ updateChildrenLayersEnabled();
// we intercept and reject all touch events when we're small, so be sure to reset the state
mTouchState = TOUCH_STATE_REST;
@@ -1296,24 +1326,11 @@
float finalAlpha = 1.0f;
float extraShrinkFactor = 1.0f;
- if (shrinkState == ShrinkState.BOTTOM_VISIBLE) {
- y = screenHeight - y - scaledPageHeight;
- } else if (shrinkState == ShrinkState.BOTTOM_HIDDEN) {
- // We shrink and disappear to nothing in the case of all apps
- // (which is when we shrink to the bottom)
- y = screenHeight - y - scaledPageHeight;
- finalAlpha = 0.0f;
- } else if (shrinkState == ShrinkState.MIDDLE) {
- y = screenHeight / 2 - scaledPageHeight / 2;
- finalAlpha = 1.0f;
- }
+ // We shrink and disappear to nothing
+ y = screenHeight - y - scaledPageHeight;
+ finalAlpha = 0.0f;
- int duration;
- if (shrinkState == ShrinkState.BOTTOM_HIDDEN || shrinkState == ShrinkState.BOTTOM_VISIBLE) {
- duration = res.getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
- } else {
- duration = res.getInteger(R.integer.config_customizeWorkspaceShrinkTime);
- }
+ int duration = res.getInteger(R.integer.config_appsCustomizeWorkspaceShrinkTime);
// We animate all the screens to the centered position in workspace
// At the same time, the screens become greyed/dimmed
@@ -1403,13 +1420,11 @@
if (enableWallpaperEffects) {
switch (shrinkState) {
// animating in
- case MIDDLE:
case SPRING_LOADED:
wallpaperOffset = 0.5f;
mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
break;
- case BOTTOM_HIDDEN:
- case BOTTOM_VISIBLE:
+ case SMALL:
// allapps
wallpaperOffset = 0.5f - offsetFromCenter;
mWallpaperOffset.setVerticalCatchupConstant(isLandscape ? 0.34f : 0.32f);
@@ -1582,7 +1597,7 @@
public void unshrink(CellLayout clThatWasClicked, boolean springLoaded) {
int newCurrentPage = indexOfChild(clThatWasClicked);
- if (mIsSmall) {
+ if (isSmall()) {
if (springLoaded) {
setLayoutScale(mSpringLoadedShrinkFactor);
}
@@ -1593,11 +1608,10 @@
public void enterSpringLoadedDragMode(CellLayout clThatWasClicked) {
- mShrinkState = ShrinkState.SPRING_LOADED;
unshrink(clThatWasClicked, true);
}
- public void exitSpringLoadedDragMode(ShrinkState shrinkState) {
+ public void exitSpringLoadedDragMode(State shrinkState) {
shrink(shrinkState);
}
@@ -1611,15 +1625,14 @@
}
void unshrink(boolean animated, boolean springLoaded) {
- mWaitingToShrink = false;
- if (mIsSmall) {
+ if (isSmall()) {
float finalScaleFactor = 1.0f;
float finalBackgroundAlpha = 0.0f;
if (springLoaded) {
finalScaleFactor = mSpringLoadedShrinkFactor;
finalBackgroundAlpha = 1.0f;
} else {
- mIsSmall = false;
+ mState = springLoaded ? State.SPRING_LOADED : State.NORMAL;
}
if (mAnimator != null) {
mAnimator.cancel();
@@ -1712,9 +1725,8 @@
final boolean enableWallpaperEffects =
isHardwareAccelerated() && LauncherApplication.isScreenLarge();
if (enableWallpaperEffects) {
- switch (mShrinkState) {
+ switch (mState) {
// animating out
- case MIDDLE:
case SPRING_LOADED:
if (animated) {
mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.49f : 0.46f);
@@ -1722,8 +1734,7 @@
mWallpaperOffset.setOverrideHorizontalCatchupConstant(true);
}
break;
- case BOTTOM_HIDDEN:
- case BOTTOM_VISIBLE:
+ case SMALL:
// all apps
if (animated) {
mWallpaperOffset.setHorizontalCatchupConstant(isLandscape ? 0.65f : 0.65f);
@@ -1818,32 +1829,57 @@
* @param destCanvas the canvas to draw on
* @param padding the horizontal and vertical padding to use when drawing
*/
- private void drawDragView(View v, Canvas destCanvas, int padding) {
+ private void drawDragView(View v, Canvas destCanvas, int padding, boolean pruneToDrawable) {
final Rect clipRect = mTempRect;
v.getDrawingRect(clipRect);
- // For a TextView, adjust the clip rect so that we don't include the text label
- if (v instanceof BubbleTextView) {
- final BubbleTextView tv = (BubbleTextView) v;
- clipRect.bottom = tv.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V +
- tv.getLayout().getLineTop(0);
- } else if (v instanceof TextView) {
- final TextView tv = (TextView) v;
- clipRect.bottom = tv.getExtendedPaddingTop() - tv.getCompoundDrawablePadding() +
- tv.getLayout().getLineTop(0);
- } else if (v instanceof FolderIcon) {
- clipRect.bottom = getResources().getDimensionPixelSize(R.dimen.folder_preview_size);
+ destCanvas.save();
+ if (v instanceof TextView && pruneToDrawable) {
+ Drawable d = ((TextView) v).getCompoundDrawables()[1];
+ clipRect.set(0, 0, d.getIntrinsicWidth() + padding, d.getIntrinsicHeight() + padding);
+ destCanvas.translate(padding / 2, padding / 2);
+ d.draw(destCanvas);
+ } else {
+ if (v instanceof FolderIcon) {
+ clipRect.bottom = getResources().getDimensionPixelSize(R.dimen.folder_preview_size);
+ } else if (v instanceof BubbleTextView) {
+ final BubbleTextView tv = (BubbleTextView) v;
+ clipRect.bottom = tv.getExtendedPaddingTop() - (int) BubbleTextView.PADDING_V +
+ tv.getLayout().getLineTop(0);
+ } else if (v instanceof TextView) {
+ final TextView tv = (TextView) v;
+ clipRect.bottom = tv.getExtendedPaddingTop() - tv.getCompoundDrawablePadding() +
+ tv.getLayout().getLineTop(0);
+ }
+ destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
+ destCanvas.clipRect(clipRect, Op.REPLACE);
+ v.draw(destCanvas);
+ }
+ destCanvas.restore();
+ }
+
+ /**
+ * Returns a new bitmap to show when the given View is being dragged around.
+ * Responsibility for the bitmap is transferred to the caller.
+ */
+ public Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
+ final int outlineColor = getResources().getColor(R.color.drag_outline_color);
+ Bitmap b;
+
+ if (v instanceof TextView) {
+ Drawable d = ((TextView) v).getCompoundDrawables()[1];
+ b = Bitmap.createBitmap(d.getIntrinsicWidth() + padding,
+ d.getIntrinsicHeight() + padding, Bitmap.Config.ARGB_8888);
+ } else {
+ b = Bitmap.createBitmap(
+ v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
}
- // Draw the View into the bitmap.
- // The translate of scrollX and scrollY is necessary when drawing TextViews, because
- // they set scrollX and scrollY to large values to achieve centered text
+ canvas.setBitmap(b);
+ drawDragView(v, canvas, padding, true);
+ mOutlineHelper.applyOuterBlur(b, canvas, outlineColor);
- destCanvas.save();
- destCanvas.translate(-v.getScrollX() + padding / 2, -v.getScrollY() + padding / 2);
- destCanvas.clipRect(clipRect, Op.REPLACE);
- v.draw(destCanvas);
- destCanvas.restore();
+ return b;
}
/**
@@ -1856,7 +1892,7 @@
v.getWidth() + padding, v.getHeight() + padding, Bitmap.Config.ARGB_8888);
canvas.setBitmap(b);
- drawDragView(v, canvas, padding);
+ drawDragView(v, canvas, padding, false);
mOutlineHelper.applyMediumExpensiveOutlineWithBlur(b, canvas, outlineColor, outlineColor);
return b;
}
@@ -1910,23 +1946,6 @@
return b;
}
- /**
- * Returns a new bitmap to show when the given View is being dragged around.
- * Responsibility for the bitmap is transferred to the caller.
- */
- private Bitmap createDragBitmap(View v, Canvas canvas, int padding) {
- final int outlineColor = getResources().getColor(R.color.drag_outline_color);
- final Bitmap b = Bitmap.createBitmap(
- mDragOutline.getWidth(), mDragOutline.getHeight(), Bitmap.Config.ARGB_8888);
-
- canvas.setBitmap(b);
- canvas.drawBitmap(mDragOutline, 0, 0, null);
- drawDragView(v, canvas, padding);
- mOutlineHelper.applyOuterBlur(b, canvas, outlineColor);
-
- return b;
- }
-
void startDrag(CellLayout.CellInfo cellInfo) {
View child = cellInfo.cell;
@@ -1950,9 +1969,15 @@
// The outline is used to visualize where the item will land if dropped
mDragOutline = createDragOutline(child, canvas, bitmapPadding);
+ beginDragShared(child, this);
+ }
+
+ public void beginDragShared(View child, DragSource source) {
+ // We need to add extra padding to the bitmap to make room for the glow effect
+ final int bitmapPadding = HolographicOutlineHelper.MAX_OUTER_BLUR_RADIUS;
// The drag bitmap follows the touch point around on the screen
- final Bitmap b = createDragBitmap(child, canvas, bitmapPadding);
+ final Bitmap b = createDragBitmap(child, new Canvas(), bitmapPadding);
final int bmpWidth = b.getWidth();
final int bmpHeight = b.getHeight();
@@ -1974,10 +1999,10 @@
dragRect = new Rect(0, 0, child.getWidth(), previewSize);
}
- mLauncher.lockScreenOrientation();
- mDragController.startDrag(b, dragLayerX, dragLayerY, this, child.getTag(),
+ mDragController.startDrag(b, dragLayerX, dragLayerY, source, child.getTag(),
DragController.DRAG_ACTION_MOVE, dragRect);
b.recycle();
+ mLauncher.lockScreenOrientation();
}
void addApplicationShortcut(ShortcutInfo info, int screen, int cellX, int cellY,
@@ -2096,7 +2121,7 @@
}
Rect folderLocation = new Rect();
- mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation);
+ float scale = mLauncher.getDragLayer().getDescendantRectRelativeToSelf(v, folderLocation);
target.removeView(v);
FolderIcon fi = mLauncher.addFolder(screen, targetCell[0], targetCell[1]);
@@ -2105,7 +2130,7 @@
sourceInfo.cellX = -1;
sourceInfo.cellY = -1;
- fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation,
+ fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale,
postAnimationRunnable);
return true;
}
@@ -2145,7 +2170,7 @@
// new current/default screen, so any subsequent taps add items to that screen
if (!mLauncher.isAllAppsVisible()) {
int dragTargetIndex = indexOfChild(mDragTargetLayout);
- if (mCurrentPage != dragTargetIndex && (mIsSmall || mIsInUnshrinkAnimation)) {
+ if (mCurrentPage != dragTargetIndex && (isSmall() || mIsSwitchingState)) {
scrollToNewPageWithoutMovingPages(dragTargetIndex);
}
}
@@ -2188,7 +2213,7 @@
(int) mDragViewVisualCenter[1], mDragInfo.spanX, mDragInfo.spanY, cell,
dropTargetLayout, mTargetCell);
- if (dropInscrollArea && mShrinkState != ShrinkState.SPRING_LOADED) {
+ if (dropInscrollArea && mState != State.SPRING_LOADED) {
snapToPage(screen);
}
@@ -2246,7 +2271,16 @@
// Prepare it to be animated into its new position
// This must be called after the view has been re-parented
- mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell);
+ final Runnable disableHardwareLayersRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mAnimatingViewIntoPlace = false;
+ updateChildrenLayersEnabled();
+ }
+ };
+ mAnimatingViewIntoPlace = true;
+ mLauncher.getDragLayer().animateViewIntoPosition(d.dragView, cell,
+ disableHardwareLayersRunnable);
parent.onDropChild(cell);
}
}
@@ -2618,7 +2652,7 @@
public void onDragOver(DragObject d) {
// Skip drag over events while we are dragging over side pages
if (mInScrollArea) return;
- if (mIsInUnshrinkAnimation) return;
+ if (mIsSwitchingState) return;
CellLayout layout;
ItemInfo item = (ItemInfo) d.dragInfo;
@@ -2627,7 +2661,7 @@
if (item.spanX < 0 || item.spanY < 0) throw new RuntimeException("Improper spans found");
// Identify whether we have dragged over a side page
- if (mIsSmall) {
+ if (isSmall()) {
int left = d.x - d.xOffset;
int top = d.y - d.yOffset;
layout = findMatchingPageForDragOver(d.dragView, left, top, d.xOffset, d.yOffset, true);
@@ -2647,7 +2681,7 @@
mLastDragOverView = null;
}
- boolean isInSpringLoadedMode = (mShrinkState == ShrinkState.SPRING_LOADED);
+ boolean isInSpringLoadedMode = (mState == State.SPRING_LOADED);
if (isInSpringLoadedMode) {
mSpringLoadedDragController.setAlarm(mDragTargetLayout);
}
@@ -2800,7 +2834,7 @@
}
};
final int screen = indexOfChild(cellLayout);
- if (screen != mCurrentPage && mShrinkState != ShrinkState.SPRING_LOADED) {
+ if (screen != mCurrentPage && mState != State.SPRING_LOADED) {
snapToPage(screen);
}
if (dragInfo instanceof PendingAddItemInfo) {
@@ -2940,6 +2974,12 @@
mLauncher = launcher;
mSpringLoadedDragController = new SpringLoadedDragController(mLauncher);
mDragController = dragController;
+
+
+ // hardware layers on children are enabled on startup, but should be disabled until
+ // needed
+ updateChildrenLayersEnabled();
+ setWallpaperDimension();
}
/**
@@ -2947,13 +2987,14 @@
*/
public void onDropCompleted(View target, DragObject d, boolean success) {
if (success) {
- if (target != this && mDragInfo != null) {
- final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
- cellLayout.removeView(mDragInfo.cell);
- if (mDragInfo.cell instanceof DropTarget) {
- mDragController.removeDropTarget((DropTarget) mDragInfo.cell);
+ if (target != this) {
+ if (mDragInfo != null) {
+ final CellLayout cellLayout = (CellLayout) getChildAt(mDragInfo.screen);
+ cellLayout.removeView(mDragInfo.cell);
+ if (mDragInfo.cell instanceof DropTarget) {
+ mDragController.removeDropTarget((DropTarget) mDragInfo.cell);
+ }
}
- // final Object tag = mDragInfo.cell.getTag();
}
} else if (mDragInfo != null) {
// NOTE: When 'success' is true, onDragExit is called by the DragController before
@@ -2984,7 +3025,7 @@
@Override
public void scrollLeft() {
- if (!mIsSmall && !mIsInUnshrinkAnimation) {
+ if (!isSmall() && !mIsSwitchingState) {
super.scrollLeft();
}
Folder openFolder = getOpenFolder();
@@ -2995,7 +3036,7 @@
@Override
public void scrollRight() {
- if (!mIsSmall && !mIsInUnshrinkAnimation) {
+ if (!isSmall() && !mIsSwitchingState) {
super.scrollRight();
}
Folder openFolder = getOpenFolder();
@@ -3006,7 +3047,7 @@
@Override
public void onEnterScrollArea(int direction) {
- if (!mIsSmall && !mIsInUnshrinkAnimation) {
+ if (!isSmall() && !mIsSwitchingState) {
mInScrollArea = true;
final int page = mCurrentPage + (direction == DragController.SCROLL_LEFT ? -1 : 1);
@@ -3239,7 +3280,7 @@
}
void moveToDefaultScreen(boolean animate) {
- if (mIsSmall || mIsInUnshrinkAnimation) {
+ if (isSmall() || mIsSwitchingState) {
mLauncher.showWorkspace(animate, (CellLayout)getChildAt(mDefaultPage));
} else if (animate) {
snapToPage(mDefaultPage);