summaryrefslogtreecommitdiffstats
path: root/src/com
diff options
context:
space:
mode:
authorJoe Onorato <joeo@android.com>2009-09-08 12:34:22 -0700
committerJoe Onorato <joeo@android.com>2009-09-11 12:14:19 -0400
commit85a02a8d13eced310aee4c2a795e9c9c5435038f (patch)
treec7fda8f70dadc9d1b4f85ba85d56e26b63408061 /src/com
parent8355ae39ad77b8e2e9ff3b4cbff8077a002ce151 (diff)
downloadandroid_packages_apps_Trebuchet-85a02a8d13eced310aee4c2a795e9c9c5435038f.tar.gz
android_packages_apps_Trebuchet-85a02a8d13eced310aee4c2a795e9c9c5435038f.tar.bz2
android_packages_apps_Trebuchet-85a02a8d13eced310aee4c2a795e9c9c5435038f.zip
Add the animation for when you enter the all apps view.
Diffstat (limited to 'src/com')
-rw-r--r--src/com/android/launcher2/AllAppsView.java31
-rw-r--r--src/com/android/launcher2/DragLayer.java53
-rw-r--r--src/com/android/launcher2/Launcher.java102
-rw-r--r--src/com/android/launcher2/SwipeController.java222
-rw-r--r--src/com/android/launcher2/Workspace.java57
5 files changed, 424 insertions, 41 deletions
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index dcaaaa118..5128db332 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -66,6 +66,7 @@ public class AllAppsView extends RSSurfaceView
private Launcher mLauncher;
private DragController mDragController;
+ private boolean mLocked = true;
private RenderScript mRS;
private RolloRS mRollo;
@@ -163,12 +164,16 @@ public class AllAppsView extends RSSurfaceView
@Override
public boolean onTouchEvent(MotionEvent ev)
{
- super.onTouchEvent(ev);
-
if (mRollo.mState.visible == 0) {
- return false;
+ return true;
}
+ if (mLocked) {
+ return true;
+ }
+
+ super.onTouchEvent(ev);
+
mTouchHandler = mFlingHandler;
/*
int action = ev.getAction();
@@ -287,15 +292,31 @@ public class AllAppsView extends RSSurfaceView
public void onDropCompleted(View target, boolean success) {
}
+ private static final int SCALE_SCALE = 100000;
+
public void show() {
mRollo.mState.read();
mRollo.mState.visible = 1;
+ mRollo.mState.zoom = SCALE_SCALE;
+ mRollo.mState.save();
+ }
+
+ public void setScale(float amount) {
+ mRollo.mState.read();
+ if (amount > 0.001f) {
+ mRollo.mState.visible = 1;
+ mRollo.mState.zoom = (int)(SCALE_SCALE*amount);
+ } else {
+ mRollo.mState.visible = 0;
+ mRollo.mState.zoom = 0;
+ }
mRollo.mState.save();
}
- public void hide(boolean animate) {
+ public void hide() {
mRollo.mState.read();
mRollo.mState.visible = 0;
+ mRollo.mState.zoom = 0;
mRollo.mState.save();
}
@@ -341,6 +362,7 @@ public class AllAppsView extends RSSurfaceView
}
mPageCount = countPages(list.size());
Log.d(TAG, "setApps mRollo=" + mRollo + " list=" + list);
+ mLocked = false;
}
private void invokeIcon(int index) {
@@ -427,6 +449,7 @@ public class AllAppsView extends RSSurfaceView
@AllocationIndex(9) public int selectedIconIndex = -1;
@AllocationIndex(10) public int selectedIconTexture;
@AllocationIndex(11) public int visible;
+ @AllocationIndex(12) public int zoom;
}
public RolloRS() {
diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java
index 28397119a..f038c2a5c 100644
--- a/src/com/android/launcher2/DragLayer.java
+++ b/src/com/android/launcher2/DragLayer.java
@@ -40,8 +40,17 @@ import android.widget.FrameLayout;
* A ViewGroup that coordinated dragging across its dscendants
*/
public class DragLayer extends FrameLayout {
+ private static final String TAG = "Launcher.DragLayer";
+
+ private static final int DRAG = 1;
+ private static final int SWIPE = 2;
+ private static final int BOTH = DRAG | SWIPE;
DragController mDragController;
+ SwipeController mSwipeController;
+
+ private int mAllowed = BOTH;
+
/**
* Used to create a new DragLayer from XML.
@@ -57,6 +66,10 @@ public class DragLayer extends FrameLayout {
mDragController = controller;
}
+ public void setSwipeController(SwipeController controller) {
+ mSwipeController = controller;
+ }
+
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event);
@@ -64,11 +77,47 @@ public class DragLayer extends FrameLayout {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
- return mDragController.onInterceptTouchEvent(ev);
+ boolean result = false;
+
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mAllowed = BOTH;
+ }
+
+ if ((mAllowed & DRAG) != 0) {
+ result = mDragController.onInterceptTouchEvent(ev);
+ if (result) {
+ mAllowed = DRAG;
+ }
+ }
+
+ if ((mAllowed & SWIPE) != 0) {
+ result = mSwipeController.onInterceptTouchEvent(ev);
+ if (result) {
+ mAllowed = SWIPE;
+ }
+ }
+
+ return result;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
- return mDragController.onTouchEvent(ev);
+ boolean result = false;
+
+ if ((mAllowed & DRAG) != 0) {
+ result = mDragController.onTouchEvent(ev);
+ if (result) {
+ mAllowed = DRAG;
+ }
+ }
+
+ if ((mAllowed & SWIPE) != 0) {
+ result = mSwipeController.onTouchEvent(ev);
+ if (result) {
+ mAllowed = SWIPE;
+ }
+ }
+
+ return result;
}
}
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index b53fee26c..86914b0cd 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -82,7 +82,8 @@ import java.io.DataInputStream;
* Default launcher application.
*/
public final class Launcher extends Activity
- implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks {
+ implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
+ SwipeController.SwipeListener {
static final String LOG_TAG = "Launcher";
static final String TAG = LOG_TAG;
static final boolean LOGD = false;
@@ -108,6 +109,10 @@ public final class Launcher extends Activity
private static final int REQUEST_PICK_LIVE_FOLDER = 8;
private static final int REQUEST_PICK_APPWIDGET = 9;
+ private static final int MODE_WORKSPACE = 0;
+ private static final int MODE_ALL_APPS = 1;
+ private static final int MODE_ALL_APPS_ZOOMED = 2;
+
static final String EXTRA_SHORTCUT_DUPLICATE = "duplicate";
static final String EXTRA_CUSTOM_WIDGET = "custom_widget";
@@ -158,6 +163,7 @@ public final class Launcher extends Activity
private LayoutInflater mInflater;
private DragController mDragController;
+ private SwipeController mSwipeController;
private Workspace mWorkspace;
private AppWidgetManager mAppWidgetManager;
@@ -171,7 +177,8 @@ public final class Launcher extends Activity
private DeleteZone mDeleteZone;
private HandleView mHandleView;
private AllAppsView mAllAppsGrid;
- private boolean mAllAppsVisible;
+ private boolean mAllAppsVisible; // if it's visible at all
+ private int mMode = MODE_WORKSPACE;
private Bundle mSavedState;
@@ -515,13 +522,18 @@ public final class Launcher extends Activity
private void setupViews() {
mDragController = new DragController(this);
DragController dragController = mDragController;
+ mSwipeController = new SwipeController(this, this);
+ SwipeController swipeController = mSwipeController;
+ swipeController.setRange(-1, 0);
DragLayer dragLayer = (DragLayer) findViewById(R.id.drag_layer);
dragLayer.setDragController(dragController);
+ dragLayer.setSwipeController(swipeController);
mAllAppsGrid = (AllAppsView)dragLayer.findViewById(R.id.all_apps_view);
mAllAppsGrid.setLauncher(this);
mAllAppsGrid.setDragController(dragController);
+ mAllAppsGrid.setWillNotDraw(false); // We don't want a hole punched in our window.
mWorkspace = (Workspace) dragLayer.findViewById(R.id.workspace);
final Workspace workspace = mWorkspace;
@@ -1422,6 +1434,7 @@ public final class Launcher extends Activity
}
if (mWorkspace.allowLongPress()) {
+ mSwipeController.cancelSwipe();
if (cellInfo.cell == null) {
if (cellInfo.valid) {
// User long pressed on empty space
@@ -1607,7 +1620,7 @@ public final class Launcher extends Activity
void closeAllAppsDialog(boolean animated) {
if (mAllAppsVisible) {
Log.d(LOG_TAG, "closing all apps");
- mAllAppsGrid.hide(animated);
+ mAllAppsGrid.hide();
mAllAppsVisible = false;
mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus();
mWorkspace.show();
@@ -1744,6 +1757,89 @@ public final class Launcher extends Activity
}
/**
+ * Implementation of the method from SwipeController.SwipeListener.
+ */
+ public void onStartSwipe() {
+ switch (mMode) {
+ case MODE_WORKSPACE:
+ mWorkspace.enableChildrenCache();
+ break;
+ case MODE_ALL_APPS:
+ break;
+ case MODE_ALL_APPS_ZOOMED:
+ break;
+ }
+ }
+
+ /**
+ * Implementation of the method from SwipeController.SwipeListener.
+ *
+ * @param amount The final value of the swipe (-1, 0 or 1)
+ */
+ public void onFinishSwipe(int amount) {
+ switch (mMode) {
+ case MODE_WORKSPACE:
+ if (amount == -1) {
+ mWorkspace.clearChildrenCache();
+ mMode = MODE_ALL_APPS;
+ mSwipeController.setRange(0, 1);
+ }
+ break;
+ case MODE_ALL_APPS:
+ if (amount == 1) {
+ mWorkspace.clearChildrenCache();
+ mMode = MODE_WORKSPACE;
+ mSwipeController.setRange(-1, 0);
+ }
+ break;
+ case MODE_ALL_APPS_ZOOMED:
+ break;
+ }
+ }
+
+ /**
+ * Implementation of the method from SwipeController.SwipeListener.
+ */
+ public void onSwipe(float amount) {
+ switch (mMode) {
+ case MODE_WORKSPACE:
+ // We can open the all apps view.
+ // 0 == workspace is showing
+ // -1 == all apps is showing
+ setWorkspaceAndAllAppsScale(-amount);
+ break;
+ case MODE_ALL_APPS:
+ // We can close it, or (someday) zoom it further
+ // 0 == all apps showing
+ // 1 == workspace is showing
+ setWorkspaceAndAllAppsScale(1-amount);
+ break;
+ }
+ }
+
+ /**
+ * Set the scale factor for the workspace and the all apps grid.
+ *
+ * @param amount A float between 0 and 1, where:
+ * 0 == workspace is showing and
+ * 1 == the all apps grid is showing.
+ */
+ private void setWorkspaceAndAllAppsScale(float amount) {
+ //Log.d("setWorkspaceAndAllAppsScale", "setWorkspaceAndAllAppsScale amount=" + amount);
+ if (amount < 0.001f) {
+ amount = 0.0f;
+ }
+ if (amount > 0.999f) {
+ amount = 1.0f;
+ mWorkspace.setVisibility(View.INVISIBLE);
+ } else {
+ mWorkspace.setVisibility(View.VISIBLE);
+ }
+ mWorkspace.setScale(1-amount);
+ mAllAppsGrid.setScale(amount);
+ }
+
+ /**
* Implementation of the method from LauncherModel.Callbacks.
*/
public int getCurrentWorkspaceScreen() {
diff --git a/src/com/android/launcher2/SwipeController.java b/src/com/android/launcher2/SwipeController.java
new file mode 100644
index 000000000..7443b3bbc
--- /dev/null
+++ b/src/com/android/launcher2/SwipeController.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2008 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.os.Handler;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.DisplayMetrics;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.ViewConfiguration;
+
+import java.util.ArrayList;
+
+public class SwipeController {
+ private static final String TAG = "Launcher.SwipeController";
+
+ private static final int FRAME_DELAY = 1000 / 30;
+ private static final float DECAY_CONSTANT = 0.65f;
+ private static final float SPRING_CONSTANT = 0.0009f;
+
+ // configuration
+ private SwipeListener mListener;
+ private int mSlop;
+ private float mSwipeDistance;
+
+ // state
+ private VelocityTracker mVelocityTracker;
+ private boolean mCanceled;
+ private boolean mTracking;
+ private int mDownX;
+ private int mDownY;
+
+ private float mMinDest;
+ private float mMaxDest;
+ private long mFlingTime;
+ private long mLastTime;
+ private int mDirection;
+ private float mVelocity;
+ private float mDest;
+ private float mAmount;
+
+ public interface SwipeListener {
+ public void onStartSwipe();
+ public void onFinishSwipe(int amount);
+ public void onSwipe(float amount);
+ }
+
+ public SwipeController(Context context, SwipeListener listener) {
+ ViewConfiguration config = ViewConfiguration.get(context);
+ mSlop = config.getScaledTouchSlop();
+
+ DisplayMetrics display = context.getResources().getDisplayMetrics();
+ mSwipeDistance = display.heightPixels / 2; // one half of the screen
+
+ mListener = listener;
+ }
+
+ public void setRange(float min, float max) {
+ mMinDest = min;
+ mMaxDest = max;
+ }
+
+ public void cancelSwipe() {
+ mCanceled = true;
+ }
+
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ onTouchEvent(ev);
+
+ // After we return true, onIntercept doesn't get called any more, so this is
+ // a good place to do the callback.
+ if (mTracking) {
+ mListener.onStartSwipe();
+ }
+
+ return mTracking;
+ }
+
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (mVelocityTracker == null) {
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+ mVelocityTracker.addMovement(ev);
+
+ final int screenX = (int)ev.getRawX();
+ final int screenY = (int)ev.getRawY();
+
+ final int deltaX = screenX - mDownX;
+ final int deltaY = screenY - mDownY;
+
+ final int action = ev.getAction();
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ // Remember location of down touch
+ mCanceled = false;
+ mTracking = false;
+ mDownX = screenX;
+ mDownY = screenY;
+ break;
+
+ case MotionEvent.ACTION_MOVE:
+ if (!mCanceled && !mTracking) {
+ if (Math.abs(deltaX) > mSlop) {
+ mCanceled = true;
+ mTracking = false;
+ }
+ if (Math.abs(deltaY) > mSlop) {
+ mTracking = true;
+ }
+ }
+ if (mTracking && !mCanceled) {
+ track(screenY);
+ }
+ break;
+
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ if (mTracking && !mCanceled) {
+ fling(screenY);
+ }
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ break;
+ }
+
+ return mTracking || mCanceled;
+ }
+
+ private float clamp(float v) {
+ if (v < mMinDest) {
+ return mMinDest;
+ } else if (v > mMaxDest) {
+ return mMaxDest;
+ } else {
+ return v;
+ }
+ }
+
+ /**
+ * Perform the callbacks.
+ */
+ private void track(int screenY) {
+ mAmount = clamp((screenY - mDownY) / mSwipeDistance);
+ mListener.onSwipe(mAmount);
+ }
+
+ private void fling(int screenY) {
+ mVelocityTracker.computeCurrentVelocity(1);
+
+ mVelocity = mVelocityTracker.getYVelocity() / mSwipeDistance;
+ mDirection = mVelocity >= 0.0f ? 1 : -1;
+ mAmount = clamp((screenY-mDownY)/mSwipeDistance);
+ if (mAmount < 0) {
+ mDest = clamp(mVelocity < 0 ? -1.0f : 0.0f);
+ } else {
+ mDest = clamp(mVelocity < 0 ? 0.0f : 1.0f);
+ }
+
+ mFlingTime = SystemClock.uptimeMillis();
+ mLastTime = 0;
+
+ scheduleAnim();
+ }
+
+ private void scheduleAnim() {
+ boolean send = true;
+ if (mDirection > 0) {
+ if (mAmount > (mDest - 0.01f)) {
+ send = false;
+ }
+ } else {
+ if (mAmount < (mDest + 0.01f)) {
+ send = false;
+ }
+ }
+ if (send) {
+ mHandler.sendEmptyMessageDelayed(1, FRAME_DELAY);
+ } else {
+ mListener.onFinishSwipe((int)(mAmount >= 0 ? (mAmount+0.5f) : (mAmount-0.5f)));
+ }
+ }
+
+ Handler mHandler = new Handler() {
+ public void handleMessage(Message msg) {
+ long now = SystemClock.uptimeMillis();
+
+ final long t = now - mFlingTime;
+ final long dt = t - mLastTime;
+ mLastTime = t;
+ final float timeSlices = dt / (float)FRAME_DELAY;
+
+ float distance = mDest - mAmount;
+
+ mVelocity += timeSlices * mDirection * SPRING_CONSTANT * distance * distance / 2;
+ mVelocity *= (timeSlices * DECAY_CONSTANT);
+
+ mAmount += timeSlices * mVelocity;
+ mAmount += distance * timeSlices * 0.2f; // cheat
+
+ mListener.onSwipe(mAmount);
+ scheduleAnim();
+ }
+ };
+}
+
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 744cf720f..14b77f037 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -46,8 +46,9 @@ import java.util.ArrayList;
* screen contains a number of icons, folders or widgets the user can interact with.
* A workspace is meant to be used with a fixed width only.
*/
-public class Workspace extends ViewGroup implements DropTarget, DragSource, DragScroller,
- TweenCallback {
+public class Workspace extends ViewGroup implements DropTarget, DragSource, DragScroller {
+ private static final String TAG = "Launcher.Workspace";
+
private static final int INVALID_SCREEN = -1;
/**
@@ -66,9 +67,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
- private SymmetricalLinearTween mTween;
- private int mAlpha = 255;
-
/**
* CellInfo for the cell that is currently being dragged
*/
@@ -150,8 +148,6 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
-
- mTween = new SymmetricalLinearTween(true, 250/*ms*/, this);
}
@Override
@@ -486,12 +482,24 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
int restoreCount = 0;
// For the fade. If view gets setAlpha(), use that instead.
- int alpha = mAlpha;
- if (alpha < 255) {
+ float scale = mScale;
+ if (scale < 0.999f) {
int sx = mScrollX;
+
+ int alpha = (scale < 0.5f) ? (int)(255 * 2 * scale) : 255;
+
restoreCount = canvas.saveLayerAlpha(sx, 0, sx+getWidth(), getHeight(), alpha,
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
restore = true;
+
+ if (scale < 0.999f) {
+ int w = getWidth();
+ w += 2 * mCurrentScreen * w;
+ int h = getHeight();
+ canvas.translate(w/2, h/2);
+ canvas.scale(scale, scale);
+ canvas.translate(-w/2, -h/2);
+ }
}
// ViewGroup.dispatchDraw() supports many features we don't need:
@@ -499,7 +507,8 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
// children, etc. The following implementation attempts to fast-track
// the drawing dispatch by drawing only what we know needs to be drawn.
- boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN;
+ boolean fastDraw = mTouchState != TOUCH_STATE_SCROLLING && mNextScreen == INVALID_SCREEN
+ && scale > 0.999f;
// If we are not scrolling or flinging, draw only the current screen
if (fastDraw) {
drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime());
@@ -524,6 +533,12 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
}
}
+ private float mScale = 1.0f;
+ public void setScale(float scale) {
+ mScale = scale;
+ invalidate();
+ }
+
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mDragController.setWindowToken(getWindowToken());
@@ -1335,31 +1350,9 @@ public class Workspace extends ViewGroup implements DropTarget, DragSource, Drag
}
void show() {
- mTween.start(true);
setVisibility(VISIBLE);
}
void hide() {
- mTween.start(false);
- }
-
- public void onTweenValueChanged(float value, float oldValue) {
- mAlpha = (int)(255*value);
- invalidate();
- }
-
- public void onTweenStarted() {
- // TODO: This conflicts with the cache for drawing. Ref count instead?
- // TODO: Don't cache all three.
- enableChildrenCache();
- }
-
- public void onTweenFinished() {
- // TODO: This conflicts with the cache for drawing. Ref count instead?
- // TODO: Don't cache all three.
- clearChildrenCache();
- if (mAlpha == 0) {
- setVisibility(GONE);
- }
}
}