diff options
author | Michael Jurka <mikejurka@google.com> | 2010-08-25 17:46:15 -0700 |
---|---|---|
committer | Michael Jurka <mikejurka@google.com> | 2010-09-01 14:54:34 -0700 |
commit | 0142d49e1378a7155bcca1fb59965d9e73016dbc (patch) | |
tree | 36d700bbf061564e34f359c2ef009ede5f88d20f /src/com/android | |
parent | 6b4adbc0558fcebbd44998bd00dcd334ddbee32d (diff) | |
download | packages_apps_trebuchet-0142d49e1378a7155bcca1fb59965d9e73016dbc.zip packages_apps_trebuchet-0142d49e1378a7155bcca1fb59965d9e73016dbc.tar.gz packages_apps_trebuchet-0142d49e1378a7155bcca1fb59965d9e73016dbc.tar.bz2 |
Changed Workspace to inherit from PagedView
- adds support for seeing dimmed side-pages on
home
- adds workspace support for pages that are
smaller than workspace itself
- removing a lot of code duplicated between
PagedView and Workspace
- tested new Workspace on Nexus One, and perf.
was indistinguishable from old Workspace in my
tests
Change-Id: Ie33ab4e8b35ac01b22894cff66650bb0ece8dfcc
Diffstat (limited to 'src/com/android')
-rw-r--r-- | src/com/android/launcher2/CellLayout.java | 4 | ||||
-rw-r--r-- | src/com/android/launcher2/Folder.java | 2 | ||||
-rw-r--r-- | src/com/android/launcher2/Launcher.java | 42 | ||||
-rw-r--r-- | src/com/android/launcher2/PagedView.java | 308 | ||||
-rw-r--r-- | src/com/android/launcher2/SmoothPagedView.java | 159 | ||||
-rw-r--r-- | src/com/android/launcher2/Workspace.java | 951 |
6 files changed, 565 insertions, 901 deletions
diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index 4c08ca6..7ae26bb 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -630,10 +630,12 @@ public class CellLayout extends ViewGroup { } mDimmedBitmapAlpha = alpha; setChildrenAlpha(1.0f - mDimmedBitmapAlpha); + invalidate(); } private void setChildrenAlpha(float alpha) { - for (int i = 0; i < getChildCount(); i++) { + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++) { getChildAt(i).setAlpha(alpha); } } diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java index 4d7c666..018b284 100644 --- a/src/com/android/launcher2/Folder.java +++ b/src/com/android/launcher2/Folder.java @@ -148,7 +148,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL void onClose() { final Workspace workspace = mLauncher.getWorkspace(); - workspace.getChildAt(workspace.getCurrentScreen()).requestFocus(); + workspace.getChildAt(workspace.getCurrentPage()).requestFocus(); } void bind(FolderInfo info) { diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index 87e25dc..ae77ec8 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -790,7 +790,7 @@ public final class Launcher extends Activity final int currentScreen = savedState.getInt(RUNTIME_STATE_CURRENT_SCREEN, -1); if (currentScreen > -1) { - mWorkspace.setCurrentScreen(currentScreen); + mWorkspace.setCurrentPage(currentScreen); } final int addScreen = savedState.getInt(RUNTIME_STATE_PENDING_ADD_SCREEN, -1); @@ -963,7 +963,7 @@ public final class Launcher extends Activity */ View createShortcut(ShortcutInfo info) { return createShortcut(R.layout.application, - (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()), info); + (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info); } /** @@ -995,7 +995,7 @@ public final class Launcher extends Activity * @param cellInfo The position on screen where to create the shortcut. */ void completeAddApplication(Context context, Intent data, CellLayout.CellInfo cellInfo) { - cellInfo.screen = mWorkspace.getCurrentScreen(); + cellInfo.screen = mWorkspace.getCurrentPage(); if (!findSingleSlot(cellInfo)) return; final ShortcutInfo info = mModel.getShortcutInfo(context.getPackageManager(), @@ -1018,7 +1018,7 @@ public final class Launcher extends Activity * @param cellInfo The position on screen where to create the shortcut. */ private void completeAddShortcut(Intent data, CellLayout.CellInfo cellInfo) { - cellInfo.screen = mWorkspace.getCurrentScreen(); + cellInfo.screen = mWorkspace.getCurrentPage(); if (!findSingleSlot(cellInfo)) return; final ShortcutInfo info = mModel.addShortcut(this, data, cellInfo, false); @@ -1144,7 +1144,7 @@ public final class Launcher extends Activity } else { mWorkspace.unshrink(alreadyOnHome); } - } else if (!mWorkspace.isDefaultScreenShowing()) { + } else if (!mWorkspace.isDefaultPageShowing()) { // on the phone, we don't animate the change to the workspace if all apps is visible mWorkspace.moveToDefaultScreen(alreadyOnHome && !allAppsVisible); } @@ -1175,7 +1175,7 @@ public final class Launcher extends Activity @Override protected void onSaveInstanceState(Bundle outState) { - outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, mWorkspace.getCurrentScreen()); + outState.putInt(RUNTIME_STATE_CURRENT_SCREEN, mWorkspace.getCurrentPage()); final ArrayList<Folder> folders = mWorkspace.getOpenFolders(); if (folders.size() > 0) { @@ -1459,18 +1459,18 @@ public final class Launcher extends Activity folderInfo.title = getText(R.string.folder_name); CellLayout.CellInfo cellInfo = mAddItemCellInfo; - cellInfo.screen = mWorkspace.getCurrentScreen(); + cellInfo.screen = mWorkspace.getCurrentPage(); if (!findSingleSlot(cellInfo)) return; // Update the model LauncherModel.addItemToDatabase(this, folderInfo, LauncherSettings.Favorites.CONTAINER_DESKTOP, - mWorkspace.getCurrentScreen(), cellInfo.cellX, cellInfo.cellY, false); + mWorkspace.getCurrentPage(), cellInfo.cellX, cellInfo.cellY, false); mFolders.put(folderInfo.id, folderInfo); // Create the view FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this, - (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()), folderInfo); + (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), folderInfo); mWorkspace.addInCurrentScreen(newFolder, cellInfo.cellX, cellInfo.cellY, 1, 1, isWorkspaceLocked()); } @@ -1480,14 +1480,14 @@ public final class Launcher extends Activity } private void completeAddLiveFolder(Intent data, CellLayout.CellInfo cellInfo) { - cellInfo.screen = mWorkspace.getCurrentScreen(); + cellInfo.screen = mWorkspace.getCurrentPage(); if (!findSingleSlot(cellInfo)) return; final LiveFolderInfo info = addLiveFolder(this, data, cellInfo, false); if (!mRestoring) { final View view = LiveFolderIcon.fromXml(R.layout.live_folder_icon, this, - (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentScreen()), info); + (ViewGroup) mWorkspace.getChildAt(mWorkspace.getCurrentPage()), info); mWorkspace.addInCurrentScreen(view, cellInfo.cellX, cellInfo.cellY, 1, 1, isWorkspaceLocked()); } @@ -1788,10 +1788,10 @@ public final class Launcher extends Activity Folder openFolder = mWorkspace.getFolderForTag(folderInfo); int folderScreen; if (openFolder != null) { - folderScreen = mWorkspace.getScreenForView(openFolder); + folderScreen = mWorkspace.getPageForView(openFolder); // .. and close it closeFolder(openFolder); - if (folderScreen != mWorkspace.getCurrentScreen()) { + if (folderScreen != mWorkspace.getCurrentPage()) { // Close any folder open on the current screen closeFolder(); // Pull the folder onto this screen @@ -1972,7 +1972,7 @@ public final class Launcher extends Activity image.setOnClickListener(handler); image.setOnFocusChangeListener(handler); image.setFocusable(true); - if (i == mWorkspace.getCurrentScreen()) image.requestFocus(); + if (i == mWorkspace.getCurrentPage()) image.requestFocus(); preview.addView(image, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); @@ -2009,7 +2009,7 @@ public final class Launcher extends Activity } public void onClick(View v) { - mWorkspace.snapToScreen((Integer) v.getTag()); + mWorkspace.snapToPage((Integer) v.getTag()); v.post(this); } @@ -2019,7 +2019,7 @@ public final class Launcher extends Activity public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { - mWorkspace.snapToScreen((Integer) v.getTag()); + mWorkspace.snapToPage((Integer) v.getTag()); } } } @@ -2528,7 +2528,7 @@ public final class Launcher extends Activity mAllAppsGrid.zoom(0.0f, animated); } ((View)mAllAppsGrid).setFocusable(false); - mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus(); + mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus(); } } @@ -2752,7 +2752,7 @@ public final class Launcher extends Activity */ public int getCurrentWorkspaceScreen() { if (mWorkspace != null) { - return mWorkspace.getCurrentScreen(); + return mWorkspace.getCurrentPage(); } else { return SCREEN_COUNT / 2; } @@ -2805,7 +2805,7 @@ public final class Launcher extends Activity break; case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER: final FolderIcon newFolder = FolderIcon.fromXml(R.layout.folder_icon, this, - (ViewGroup) workspace.getChildAt(workspace.getCurrentScreen()), + (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()), (UserFolderInfo) item); workspace.addInScreen(newFolder, item.screen, item.cellX, item.cellY, 1, 1, false); @@ -2813,7 +2813,7 @@ public final class Launcher extends Activity case LauncherSettings.Favorites.ITEM_TYPE_LIVE_FOLDER: final FolderIcon newLiveFolder = LiveFolderIcon.fromXml( R.layout.live_folder_icon, this, - (ViewGroup) workspace.getChildAt(workspace.getCurrentScreen()), + (ViewGroup) workspace.getChildAt(workspace.getCurrentPage()), (LiveFolderInfo) item); workspace.addInScreen(newLiveFolder, item.screen, item.cellX, item.cellY, 1, 1, false); @@ -2876,7 +2876,7 @@ public final class Launcher extends Activity public void finishBindingItems() { if (mSavedState != null) { if (!mWorkspace.hasFocus()) { - mWorkspace.getChildAt(mWorkspace.getCurrentScreen()).requestFocus(); + mWorkspace.getChildAt(mWorkspace.getCurrentPage()).requestFocus(); } final long[] userFolders = mSavedState.getLongArray(RUNTIME_STATE_USER_FOLDERS); diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java index 6154947..5052a59 100644 --- a/src/com/android/launcher2/PagedView.java +++ b/src/com/android/launcher2/PagedView.java @@ -42,37 +42,42 @@ import com.android.launcher.R; /** * An abstraction of the original Workspace which supports browsing through a - * sequential list of "pages" (or PagedViewCellLayouts). + * sequential list of "pages" */ public abstract class PagedView extends ViewGroup { private static final String TAG = "PagedView"; - private static final int INVALID_PAGE = -1; - - // the velocity at which a fling gesture will cause us to snap to the next page - private static final int SNAP_VELOCITY = 500; + protected static final int INVALID_PAGE = -1; // the min drag distance for a fling to register, to prevent random page shifts private static final int MIN_LENGTH_FOR_FLING = 50; - private boolean mFirstLayout = true; + protected static final float NANOTIME_DIV = 1000000000.0f; + + // the velocity at which a fling gesture will cause us to snap to the next page + protected int mSnapVelocity = 500; + + protected float mSmoothingTime; + protected float mTouchX; - private int mCurrentPage; - private int mNextPage = INVALID_PAGE; - private Scroller mScroller; + protected boolean mFirstLayout = true; + + protected int mCurrentPage; + protected int mNextPage = INVALID_PAGE; + protected Scroller mScroller; private VelocityTracker mVelocityTracker; private float mDownMotionX; private float mLastMotionX; private float mLastMotionY; - private final static int TOUCH_STATE_REST = 0; - private final static int TOUCH_STATE_SCROLLING = 1; - private final static int TOUCH_STATE_PREV_PAGE = 2; - private final static int TOUCH_STATE_NEXT_PAGE = 3; + protected final static int TOUCH_STATE_REST = 0; + protected final static int TOUCH_STATE_SCROLLING = 1; + protected final static int TOUCH_STATE_PREV_PAGE = 2; + protected final static int TOUCH_STATE_NEXT_PAGE = 3; - private int mTouchState = TOUCH_STATE_REST; + protected int mTouchState = TOUCH_STATE_REST; - private OnLongClickListener mLongClickListener; + protected OnLongClickListener mLongClickListener; private boolean mAllowLongPress = true; @@ -84,13 +89,29 @@ public abstract class PagedView extends ViewGroup { private int mActivePointerId = INVALID_POINTER; + private enum PageMovingState { PAGE_BEGIN_MOVING, PAGE_END_MOVING }; private PageSwitchListener mPageSwitchListener; + private PageMovingListener mPageMovingListener; private ArrayList<Boolean> mDirtyPageContent; private boolean mDirtyPageAlpha; protected PagedViewIconCache mPageViewIconCache; + // If true, syncPages and syncPageItems will be called to refresh pages + protected boolean mContentIsRefreshable = true; + + // If true, modify alpha of neighboring pages as user scrolls left/right + protected boolean mFadeInAdjacentScreens = true; + + // It true, use a different slop parameter (pagingTouchSlop = 2 * touchSlop) for deciding + // to switch to a new page + protected boolean mUsePagingTouchSlop = true; + + // If true, the subclass should directly update mScrollX itself in its computeScroll method + // (SmoothPagedView does this) + protected boolean mDeferScrollUpdate = false; + /** * Simple cache mechanism for PagedViewIcon outlines. */ @@ -117,6 +138,11 @@ public abstract class PagedView extends ViewGroup { void onPageSwitch(View newPage, int newPageIndex); } + public interface PageMovingListener { + void onPageBeginMoving(); + void onPageEndMoving(); + } + public PagedView(Context context) { this(context, null); } @@ -129,13 +155,13 @@ public abstract class PagedView extends ViewGroup { super(context, attrs, defStyle); setHapticFeedbackEnabled(false); - initWorkspace(); + init(); } /** * Initializes various states for this workspace. */ - private void initWorkspace() { + protected void init() { mDirtyPageContent = new ArrayList<Boolean>(); mDirtyPageContent.ensureCapacity(32); mPageViewIconCache = new PagedViewIconCache(); @@ -190,12 +216,20 @@ public abstract class PagedView extends ViewGroup { notifyPageSwitchListener(); } - private void notifyPageSwitchListener() { + protected void notifyPageSwitchListener() { if (mPageSwitchListener != null) { mPageSwitchListener.onPageSwitch(getPageAt(mCurrentPage), mCurrentPage); } } + // a method that subclasses can override to add behavior + protected void pageBeginMoving() { + } + + // a method that subclasses can override to add behavior + protected void pageEndMoving() { + } + /** * Registers the specified listener on each page contained in this workspace. * @@ -211,15 +245,31 @@ public abstract class PagedView extends ViewGroup { } @Override - public void computeScroll() { + public void scrollTo(int x, int y) { + super.scrollTo(x, y); + mTouchX = x; + mSmoothingTime = System.nanoTime() / NANOTIME_DIV; + } + + // we moved this functionality to a helper function so SmoothPagedView can reuse it + protected boolean computeScrollHelper() { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); - postInvalidate(); + invalidate(); + return true; } else if (mNextPage != INVALID_PAGE) { mCurrentPage = Math.max(0, Math.min(mNextPage, getPageCount() - 1)); - notifyPageSwitchListener(); mNextPage = INVALID_PAGE; + notifyPageSwitchListener(); + pageEndMoving(); + return true; } + return false; + } + + @Override + public void computeScroll() { + computeScrollHelper(); } @Override @@ -247,6 +297,7 @@ public abstract class PagedView extends ViewGroup { if (mFirstLayout) { setHorizontalScrollBarEnabled(false); scrollTo(mCurrentPage * widthSize, 0); + mScroller.setFinalX(mCurrentPage * widthSize); setHorizontalScrollBarEnabled(true); mFirstLayout = false; } @@ -272,32 +323,67 @@ public abstract class PagedView extends ViewGroup { @Override protected void dispatchDraw(Canvas canvas) { - if (mDirtyPageAlpha || (mTouchState == TOUCH_STATE_SCROLLING) || !mScroller.isFinished()) { - int screenCenter = mScrollX + (getMeasuredWidth() / 2); - final int childCount = getChildCount(); - for (int i = 0; i < childCount; ++i) { - PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(i); - int childWidth = layout.getMeasuredWidth(); - int halfChildWidth = (childWidth / 2); - int childCenter = getChildOffset(i) + halfChildWidth; - int distanceFromScreenCenter = Math.abs(childCenter - screenCenter); - float alpha = 0.0f; - if (distanceFromScreenCenter < halfChildWidth) { - alpha = 1.0f; - } else if (distanceFromScreenCenter > childWidth) { - alpha = 0.0f; - } else { - float dimAlpha = (float) (distanceFromScreenCenter - halfChildWidth) / halfChildWidth; - dimAlpha = Math.max(0.0f, Math.min(1.0f, (dimAlpha * dimAlpha))); - alpha = 1.0f - dimAlpha; - } - if (Float.compare(alpha, layout.getAlpha()) != 0) { - layout.setAlpha(alpha); + if (mFadeInAdjacentScreens) { + if (mDirtyPageAlpha || (mTouchState == TOUCH_STATE_SCROLLING) || !mScroller.isFinished()) { + int screenCenter = mScrollX + (getMeasuredWidth() / 2); + final int childCount = getChildCount(); + for (int i = 0; i < childCount; ++i) { + View layout = (View) getChildAt(i); + int childWidth = layout.getMeasuredWidth(); + int halfChildWidth = (childWidth / 2); + int childCenter = getChildOffset(i) + halfChildWidth; + int distanceFromScreenCenter = Math.abs(childCenter - screenCenter); + float alpha = 0.0f; + if (distanceFromScreenCenter < halfChildWidth) { + alpha = 1.0f; + } else if (distanceFromScreenCenter > childWidth) { + alpha = 0.0f; + } else { + float dimAlpha = (float) (distanceFromScreenCenter - halfChildWidth) / halfChildWidth; + dimAlpha = Math.max(0.0f, Math.min(1.0f, (dimAlpha * dimAlpha))); + alpha = 1.0f - dimAlpha; + } + if (Float.compare(alpha, layout.getAlpha()) != 0) { + layout.setAlpha(alpha); + } } + mDirtyPageAlpha = false; } - mDirtyPageAlpha = false; } - super.dispatchDraw(canvas); + + // Find out which screens are visible; as an optimization we only call draw on them + + // As an optimization, this code assumes that all pages have the same width as the 0th + // page. + final int pageWidth = getChildAt(0).getMeasuredWidth(); + final int pageCount = getChildCount(); + final int screenWidth = getMeasuredWidth(); + int x = getRelativeChildOffset(0) + pageWidth; + int leftScreen = 0; + int rightScreen = 0; + while (x <= mScrollX) { + leftScreen++; + x += pageWidth; + // replace above line with this if you don't assume all pages have same width as 0th + // page: + // x += getChildAt(leftScreen).getMeasuredWidth(); + } + rightScreen = leftScreen; + while (x < mScrollX + screenWidth) { + rightScreen++; + x += pageWidth; + // replace above line with this if you don't assume all pages have same width as 0th + // page: + //if (rightScreen < pageCount) { + // x += getChildAt(rightScreen).getMeasuredWidth(); + //} + } + rightScreen = Math.min(getChildCount() - 1, rightScreen); + + final long drawingTime = getDrawingTime(); + for (int i = leftScreen; i <= rightScreen; i++) { + drawChild(canvas, getChildAt(i), drawingTime); + } } @Override @@ -466,6 +552,7 @@ public abstract class PagedView extends ViewGroup { case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: // Release the drag + pageEndMoving(); mTouchState = TOUCH_STATE_REST; mAllowLongPress = false; mActivePointerId = INVALID_POINTER; @@ -522,10 +609,13 @@ public abstract class PagedView extends ViewGroup { boolean yMoved = yDiff > touchSlop; if (xMoved || yMoved) { - if (xPaged) { + if (mUsePagingTouchSlop ? xPaged : xMoved) { // Scroll if the user moved far enough along the X axis mTouchState = TOUCH_STATE_SCROLLING; mLastMotionX = x; + mTouchX = mScrollX; + mSmoothingTime = System.nanoTime() / NANOTIME_DIV; + pageBeginMoving(); } // Either way, cancel any pending longpress if (mAllowLongPress) { @@ -561,6 +651,9 @@ public abstract class PagedView extends ViewGroup { // Remember where the motion event started mDownMotionX = mLastMotionX = ev.getX(); mActivePointerId = ev.getPointerId(0); + if (mTouchState == TOUCH_STATE_SCROLLING) { + pageBeginMoving(); + } break; case MotionEvent.ACTION_MOVE: @@ -574,14 +667,28 @@ public abstract class PagedView extends ViewGroup { int sx = getScrollX(); if (deltaX < 0) { if (sx > 0) { - scrollBy(Math.max(-sx, deltaX), 0); + mTouchX += Math.max(-mTouchX, deltaX); + mSmoothingTime = System.nanoTime() / NANOTIME_DIV; + if (!mDeferScrollUpdate) { + scrollBy(Math.max(-sx, deltaX), 0); + } else { + // This will trigger a call to computeScroll() on next drawChild() call + invalidate(); + } } } else if (deltaX > 0) { final int lastChildIndex = getChildCount() - 1; final int availableToScroll = getChildOffset(lastChildIndex) - getRelativeChildOffset(lastChildIndex) - sx; if (availableToScroll > 0) { - scrollBy(Math.min(availableToScroll, deltaX), 0); + mTouchX += Math.min(availableToScroll, deltaX); + mSmoothingTime = System.nanoTime() / NANOTIME_DIV; + if (!mDeferScrollUpdate) { + scrollBy(Math.min(availableToScroll, deltaX), 0); + } else { + // This will trigger a call to computeScroll() on next drawChild() call + invalidate(); + } } } else { awakenScrollBars(); @@ -602,11 +709,12 @@ public abstract class PagedView extends ViewGroup { int velocityX = (int) velocityTracker.getXVelocity(activePointerId); boolean isfling = Math.abs(mDownMotionX - x) > MIN_LENGTH_FOR_FLING; - if (isfling && velocityX > SNAP_VELOCITY && mCurrentPage > 0) { - snapToPage(mCurrentPage - 1); - } else if (isfling && velocityX < -SNAP_VELOCITY && + final int snapVelocity = mSnapVelocity; + if (isfling && velocityX > snapVelocity && mCurrentPage > 0) { + snapToPageWithVelocity(mCurrentPage - 1, velocityX); + } else if (isfling && velocityX < -snapVelocity && mCurrentPage < getChildCount() - 1) { - snapToPage(mCurrentPage + 1); + snapToPageWithVelocity(mCurrentPage + 1, velocityX); } else { snapToDestination(); } @@ -701,7 +809,7 @@ public abstract class PagedView extends ViewGroup { int screenCenter = mScrollX + (getMeasuredWidth() / 2); final int childCount = getChildCount(); for (int i = 0; i < childCount; ++i) { - PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(i); + View layout = (View) getChildAt(i); int childWidth = layout.getMeasuredWidth(); int halfChildWidth = (childWidth / 2); int childCenter = getChildOffset(i) + halfChildWidth; @@ -714,29 +822,47 @@ public abstract class PagedView extends ViewGroup { snapToPage(minDistanceFromScreenCenterIndex, 1000); } - void snapToPage(int whichPage) { + protected void snapToPageWithVelocity(int whichPage, int velocity) { + // We ignore velocity in this implementation, but children (e.g. SmoothPagedView) + // can use it + snapToPage(whichPage); + } + + protected void snapToPage(int whichPage) { snapToPage(whichPage, 1000); } - void snapToPage(int whichPage, int duration) { + protected void snapToPage(int whichPage, int duration) { whichPage = Math.max(0, Math.min(whichPage, getPageCount() - 1)); - mNextPage = whichPage; int newX = getChildOffset(whichPage) - getRelativeChildOffset(whichPage); final int sX = getScrollX(); final int delta = newX - sX; + snapToPage(whichPage, delta, duration); + } + + protected void snapToPage(int whichPage, int delta, int duration) { + mNextPage = whichPage; + + View focusedChild = getFocusedChild(); + if (focusedChild != null && whichPage != mCurrentPage && + focusedChild == getChildAt(mCurrentPage)) { + focusedChild.clearFocus(); + } + + pageBeginMoving(); awakenScrollBars(duration); if (duration == 0) { duration = Math.abs(delta); } if (!mScroller.isFinished()) mScroller.abortAnimation(); - mScroller.startScroll(sX, 0, delta, 0, duration); + mScroller.startScroll(getScrollX(), 0, delta, 0, duration); // only load some associated pages loadAssociatedPages(mNextPage); - + notifyPageSwitchListener(); invalidate(); } @@ -793,6 +919,14 @@ public abstract class PagedView extends ViewGroup { return mAllowLongPress; } + /** + * Set true to allow long-press events to be triggered, usually checked by + * {@link Launcher} to accept or block dpad-initiated long-presses. + */ + public void setAllowLongPress(boolean allowLongPress) { + mAllowLongPress = allowLongPress; + } + public static class SavedState extends BaseSavedState { int currentPage = -1; @@ -824,23 +958,25 @@ public abstract class PagedView extends ViewGroup { } public void loadAssociatedPages(int page) { - final int count = getChildCount(); - if (page < count) { - int lowerPageBound = Math.max(0, page - 1); - int upperPageBound = Math.min(page + 1, count - 1); - for (int i = 0; i < count; ++i) { - final PagedViewCellLayout layout = (PagedViewCellLayout) getChildAt(i); - final int childCount = layout.getChildCount(); - if (lowerPageBound <= i && i <= upperPageBound) { - if (mDirtyPageContent.get(i)) { - syncPageItems(i); - mDirtyPageContent.set(i, false); - } - } else { - if (childCount > 0) { - layout.removeAllViews(); + if (mContentIsRefreshable) { + final int count = getChildCount(); + if (page < count) { + int lowerPageBound = Math.max(0, page - 1); + int upperPageBound = Math.min(page + 1, count - 1); + for (int i = 0; i < count; ++i) { + final ViewGroup layout = (ViewGroup) getChildAt(i); + final int childCount = layout.getChildCount(); + if (lowerPageBound <= i && i <= upperPageBound) { + if (mDirtyPageContent.get(i)) { + syncPageItems(i); + mDirtyPageContent.set(i, false); + } + } else { + if (childCount > 0) { + layout.removeAllViews(); + } + mDirtyPageContent.set(i, true); } - mDirtyPageContent.set(i, true); } } } @@ -861,19 +997,21 @@ public abstract class PagedView extends ViewGroup { public abstract void syncPageItems(int page); public void invalidatePageData() { - // Update all the pages - syncPages(); + if (mContentIsRefreshable) { + // Update all the pages + syncPages(); - // Mark each of the pages as dirty - final int count = getChildCount(); - mDirtyPageContent.clear(); - for (int i = 0; i < count; ++i) { - mDirtyPageContent.add(true); - } + // Mark each of the pages as dirty + final int count = getChildCount(); + mDirtyPageContent.clear(); + for (int i = 0; i < count; ++i) { + mDirtyPageContent.add(true); + } - // Load any pages that are necessary for the current window of views - loadAssociatedPages(mCurrentPage); - mDirtyPageAlpha = true; - requestLayout(); + // Load any pages that are necessary for the current window of views + loadAssociatedPages(mCurrentPage); + mDirtyPageAlpha = true; + requestLayout(); + } } } diff --git a/src/com/android/launcher2/SmoothPagedView.java b/src/com/android/launcher2/SmoothPagedView.java new file mode 100644 index 0000000..3218349 --- /dev/null +++ b/src/com/android/launcher2/SmoothPagedView.java @@ -0,0 +1,159 @@ +/* + * 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.util.AttributeSet; +import android.view.animation.Interpolator; +import android.widget.Scroller; + + +public abstract class SmoothPagedView extends PagedView { + private static final float SMOOTHING_SPEED = 0.75f; + private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED)); + + + private static final float BASELINE_FLING_VELOCITY = 2500.f; + private static final float FLING_VELOCITY_INFLUENCE = 0.4f; + + private WorkspaceOvershootInterpolator mScrollInterpolator; + + private static class WorkspaceOvershootInterpolator implements Interpolator { + private static final float DEFAULT_TENSION = 1.3f; + private float mTension; + + public WorkspaceOvershootInterpolator() { + mTension = DEFAULT_TENSION; + } + + public void setDistance(int distance) { + mTension = distance > 0 ? DEFAULT_TENSION / distance : DEFAULT_TENSION; + } + + public void disableSettle() { + mTension = 0.f; + } + + public float getInterpolation(float t) { + // _o(t) = t * t * ((tension + 1) * t + tension) + // o(t) = _o(t - 1) + 1 + t -= 1.0f; + return t * t * ((mTension + 1) * t + mTension) + 1.0f; + } + } + + /** + * Used to inflate the Workspace from XML. + * + * @param context The application's context. + * @param attrs The attributes set containing the Workspace's customization values. + */ + public SmoothPagedView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + /** + * Used to inflate the Workspace from XML. + * + * @param context The application's context. + * @param attrs The attributes set containing the Workspace's customization values. + * @param defStyle Unused. + */ + public SmoothPagedView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + mUsePagingTouchSlop = false; + + // This means that we'll take care of updating the scroll parameter ourselves (we do it + // in computeScroll) + mDeferScrollUpdate = true; + } + + /** + * Initializes various states for this workspace. + */ + @Override + protected void init() { + super.init(); + mScrollInterpolator = new WorkspaceOvershootInterpolator(); + // overwrite the previous mScroller + mScroller = new Scroller(getContext(), mScrollInterpolator); + } + + @Override + protected void snapToDestination() { + snapToPageWithVelocity(mCurrentPage, 0); + } + + @Override + protected void snapToPageWithVelocity(int whichPage, int velocity) { + snapToPageWithVelocity(whichPage, 0, true); + } + + void snapToPageWithVelocity(int whichPage, int velocity, boolean settle) { + // if (!mScroller.isFinished()) return; + + whichPage = Math.max(0, Math.min(whichPage, getChildCount() - 1)); + + final int screenDelta = Math.max(1, Math.abs(whichPage - mCurrentPage)); + final int newX = whichPage * getWidth(); + final int delta = newX - mScrollX; + int duration = (screenDelta + 1) * 100; + + if (!mScroller.isFinished()) { + mScroller.abortAnimation(); + } + + if (settle) { + mScrollInterpolator.setDistance(screenDelta); + } else { + mScrollInterpolator.disableSettle(); + } + + velocity = Math.abs(velocity); + if (velocity > 0) { + duration += (duration / (velocity / BASELINE_FLING_VELOCITY)) + * FLING_VELOCITY_INFLUENCE; + } else { + duration += 100; + } + snapToPage(whichPage, delta, duration); + } + + @Override + protected void snapToPage(int whichPage) { + snapToPageWithVelocity(whichPage, 0, false); + } + + @Override + public void computeScroll() { + boolean scrollComputed = computeScrollHelper(); + + if (!scrollComputed && mTouchState == TOUCH_STATE_SCROLLING) { + final float now = System.nanoTime() / NANOTIME_DIV; + final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT); + final float dx = mTouchX - mScrollX; + mScrollX += dx * e; + mSmoothingTime = now; + + // Keep generating points as long as we're more than 1px away from the target + if (dx > 1.f || dx < -1.f) { + invalidate(); + } + } + } +} diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index ba45b48..7551699 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -19,10 +19,10 @@ package com.android.launcher2; import com.android.launcher.R; import android.animation.Animatable; -import android.animation.Animatable.AnimatableListener; import android.animation.PropertyAnimator; import android.animation.PropertyValuesHolder; import android.animation.Sequencer; +import android.animation.Animatable.AnimatableListener; import android.app.WallpaperManager; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; @@ -35,23 +35,16 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Matrix; -import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.IBinder; -import android.os.Parcel; import android.os.Parcelable; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; -import android.view.VelocityTracker; import android.view.View; -import android.view.ViewConfiguration; import android.view.ViewGroup; -import android.view.ViewParent; -import android.view.animation.Interpolator; -import android.widget.Scroller; import android.widget.TextView; import android.widget.Toast; @@ -59,40 +52,26 @@ import java.util.ArrayList; import java.util.HashSet; /** - * The workspace is a wide area with a wallpaper and a finite number of screens. - * Each screen contains a number of icons, folders or widgets the user can + * The workspace is a wide area with a wallpaper and a finite number of pages. + * Each page 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 +public class Workspace extends SmoothPagedView implements DropTarget, DragSource, DragScroller, View.OnTouchListener { @SuppressWarnings({"UnusedDeclaration"}) private static final String TAG = "Launcher.Workspace"; - private static final int INVALID_SCREEN = -1; + // This is how much the workspace shrinks when we enter all apps or // customization mode private static final float SHRINK_FACTOR = 0.16f; - private static final int SHRINK_TO_TOP = 0; - private static final int SHRINK_TO_MIDDLE = 1; - private static final int SHRINK_TO_BOTTOM = 2; - - /** - * The velocity at which a fling gesture will cause us to snap to the next - * screen - */ - private static final int SNAP_VELOCITY = 600; + private enum ShrinkPosition { SHRINK_TO_TOP, SHRINK_TO_MIDDLE, SHRINK_TO_BOTTOM }; private final WallpaperManager mWallpaperManager; - private int mDefaultScreen; + private int mDefaultPage; - private boolean mFirstLayout = true; private boolean mWaitingToShrinkToBottom = false; - private int mCurrentScreen; - private int mNextScreen = INVALID_SCREEN; - private Scroller mScroller; - private VelocityTracker mVelocityTracker; - /** * CellInfo for the cell that is currently being dragged */ @@ -108,16 +87,6 @@ public class Workspace extends ViewGroup */ private CellLayout mDragTargetLayout = null; - private float mLastMotionX; - private float mLastMotionY; - - private final static int TOUCH_STATE_REST = 0; - private final static int TOUCH_STATE_SCROLLING = 1; - - private int mTouchState = TOUCH_STATE_REST; - - private OnLongClickListener mLongClickListener; - private Launcher mLauncher; private IconCache mIconCache; private DragController mDragController; @@ -128,67 +97,23 @@ public class Workspace extends ViewGroup private float[] mTempDragCoordinates = new float[2]; private float[] mTempDragBottomRightCoordinates = new float[2]; - private boolean mAllowLongPress = true; - - private int mTouchSlop; - private int mMaximumVelocity; - - private static final int INVALID_POINTER = -1; private static final int DEFAULT_CELL_COUNT_X = 4; private static final int DEFAULT_CELL_COUNT_Y = 4; - private int mActivePointerId = INVALID_POINTER; - private Drawable mPreviousIndicator; private Drawable mNextIndicator; - private static final float NANOTIME_DIV = 1000000000.0f; - private static final float SMOOTHING_SPEED = 0.75f; - private static final float SMOOTHING_CONSTANT = (float) (0.016 / Math.log(SMOOTHING_SPEED)); - private float mSmoothingTime; - private float mTouchX; - - private WorkspaceOvershootInterpolator mScrollInterpolator; - - private static final float BASELINE_FLING_VELOCITY = 2500.f; - private static final float FLING_VELOCITY_INFLUENCE = 0.4f; - - private Paint mDropIndicatorPaint; - - // State variable that indicated whether the screens are small (ie when you're + // State variable that indicated whether the pages are small (ie when you're // in all apps or customize mode) private boolean mIsSmall; private AnimatableListener mUnshrinkAnimationListener; - private static class WorkspaceOvershootInterpolator implements Interpolator { - private static final float DEFAULT_TENSION = 1.3f; - private float mTension; - - public WorkspaceOvershootInterpolator() { - mTension = DEFAULT_TENSION; - } - - public void setDistance(int distance) { - mTension = distance > 0 ? DEFAULT_TENSION / distance : DEFAULT_TENSION; - } - - public void disableSettle() { - mTension = 0.f; - } - - public float getInterpolation(float t) { - // _o(t) = t * t * ((tension + 1) * t + tension) - // o(t) = _o(t - 1) + 1 - t -= 1.0f; - return t * t * ((mTension + 1) * t + mTension) + 1.0f; - } - } /** * Used to inflate the Workspace from XML. * * @param context The application's context. - * @param attrs The attribtues set containing the Workspace's customization values. + * @param attrs The attributes set containing the Workspace's customization values. */ public Workspace(Context context, AttributeSet attrs) { this(context, attrs, 0); @@ -198,11 +123,13 @@ public class Workspace extends ViewGroup * Used to inflate the Workspace from XML. * * @param context The application's context. - * @param attrs The attribtues set containing the Workspace's customization values. + * @param attrs The attributes set containing the Workspace's customization values. * @param defStyle Unused. */ public Workspace(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); + mContentIsRefreshable = false; + mFadeInAdjacentScreens = false; mWallpaperManager = WallpaperManager.getInstance(context); @@ -210,29 +137,25 @@ public class Workspace extends ViewGroup R.styleable.Workspace, defStyle, 0); int cellCountX = a.getInt(R.styleable.Workspace_cellCountX, DEFAULT_CELL_COUNT_X); int cellCountY = a.getInt(R.styleable.Workspace_cellCountY, DEFAULT_CELL_COUNT_Y); - mDefaultScreen = a.getInt(R.styleable.Workspace_defaultScreen, 1); + mDefaultPage = a.getInt(R.styleable.Workspace_defaultScreen, 1); a.recycle(); LauncherModel.updateWorkspaceLayoutCells(cellCountX, cellCountY); setHapticFeedbackEnabled(false); + initWorkspace(); } /** * Initializes various states for this workspace. */ - private void initWorkspace() { + protected void initWorkspace() { Context context = getContext(); - mScrollInterpolator = new WorkspaceOvershootInterpolator(); - mScroller = new Scroller(context, mScrollInterpolator); - mCurrentScreen = mDefaultScreen; - Launcher.setScreen(mCurrentScreen); + mCurrentPage = mDefaultPage; + Launcher.setScreen(mCurrentPage); LauncherApplication app = (LauncherApplication)context.getApplicationContext(); mIconCache = app.getIconCache(); - final ViewConfiguration configuration = ViewConfiguration.get(getContext()); - mTouchSlop = configuration.getScaledTouchSlop(); - mMaximumVelocity = configuration.getScaledMaximumFlingVelocity(); mUnshrinkAnimationListener = new AnimatableListener() { public void onAnimationStart(Animatable animation) {} public void onAnimationEnd(Animatable animation) { @@ -241,6 +164,8 @@ public class Workspace extends ViewGroup public void onAnimationCancel(Animatable animation) {} public void onAnimationRepeat(Animatable animation) {} }; + + mSnapVelocity = 600; } @Override @@ -287,10 +212,10 @@ public class Workspace extends ViewGroup * @return The open folder on the current screen, or null if there is none */ Folder getOpenFolder() { - CellLayout currentScreen = (CellLayout) getChildAt(mCurrentScreen); - int count = currentScreen.getChildCount(); + CellLayout currentPage = (CellLayout) getChildAt(mCurrentPage); + int count = currentPage.getChildCount(); for (int i = 0; i < count; i++) { - View child = currentScreen.getChildAt(i); + View child = currentPage.getChildAt(i); if (child instanceof Folder) { Folder folder = (Folder) child; if (folder.getInfo().opened) @@ -305,12 +230,10 @@ public class Workspace extends ViewGroup ArrayList<Folder> folders = new ArrayList<Folder>(screenCount); for (int screen = 0; screen < screenCount; screen++) { - CellLayout currentScreen = (CellLayout) getChildAt(screen); - int count = currentScreen.getChildCount(); + CellLayout currentPage = (CellLayout) getChildAt(screen); + int count = currentPage.getChildCount(); for (int i = 0; i < count; i++) { - View child = currentScreen.getChildAt(i); - CellLayout.LayoutParams lp = (CellLayout.LayoutParams) child - .getLayoutParams(); + View child = currentPage.getChildAt(i); if (child instanceof Folder) { Folder folder = (Folder) child; if (folder.getInfo().opened) @@ -323,47 +246,19 @@ public class Workspace extends ViewGroup return folders; } - boolean isDefaultScreenShowing() { - return mCurrentScreen == mDefaultScreen; - } - - /** - * Returns the index of the currently displayed screen. - * - * @return The index of the currently displayed screen. - */ - int getCurrentScreen() { - return mCurrentScreen; + boolean isDefaultPageShowing() { + return mCurrentPage == mDefaultPage; } /** * Sets the current screen. * - * @param currentScreen + * @param currentPage */ - void setCurrentScreen(int currentScreen) { - setCurrentScreen(currentScreen, true); - } - - void setCurrentScreen(int currentScreen, boolean animateScrolling) { - setCurrentScreen(currentScreen, animateScrolling, getWidth()); - } - - void setCurrentScreen(int currentScreen, boolean animateScrolling, int screenWidth) { - if (!mScroller.isFinished()) - mScroller.abortAnimation(); - mCurrentScreen = Math.max(0, Math.min(currentScreen, getChildCount() - 1)); - if (mPreviousIndicator != null) { - mPreviousIndicator.setLevel(mCurrentScreen); - mNextIndicator.setLevel(mCurrentScreen); - } - if (animateScrolling) { - scrollTo(mCurrentScreen * screenWidth, 0); - } else { - mScrollX = mCurrentScreen * screenWidth; - } - updateWallpaperOffset(screenWidth * (getChildCount() - 1)); - invalidate(); + @Override + void setCurrentPage(int currentPage) { + super.setCurrentPage(currentPage); + updateWallpaperOffset(mScrollX); } /** @@ -377,7 +272,7 @@ public class Workspace extends ViewGroup * @param spanY The number of cells spanned vertically by the child. */ void addInCurrentScreen(View child, int x, int y, int spanX, int spanY) { - addInScreen(child, mCurrentScreen, x, y, spanX, spanY, false); + addInScreen(child, mCurrentPage, x, y, spanX, spanY, false); } /** @@ -392,7 +287,7 @@ public class Workspace extends ViewGroup * @param insert When true, the child is inserted at the beginning of the children list. */ void addInCurrentScreen(View child, int x, int y, int spanX, int spanY, boolean insert) { - addInScreen(child, mCurrentScreen, x, y, spanX, spanY, insert); + addInScreen(child, mCurrentPage, x, y, spanX, spanY, insert); } /** @@ -463,7 +358,7 @@ public class Workspace extends ViewGroup } CellLayout.CellInfo updateOccupiedCellsForCurrentScreen(boolean[] occupied) { - CellLayout group = (CellLayout) getChildAt(mCurrentScreen); + CellLayout group = (CellLayout) getChildAt(mCurrentPage); if (group != null) { return group.updateOccupiedCells(occupied, null); } @@ -480,20 +375,38 @@ public class Workspace extends ViewGroup return false; } - /** - * Registers the specified listener on each screen contained in this workspace. - * - * @param l The listener used to respond to long clicks. - */ - @Override - public void setOnLongClickListener(OnLongClickListener l) { - mLongClickListener = l; - final int screenCount = getChildCount(); - for (int i = 0; i < screenCount; i++) { - getChildAt(i).setOnLongClickListener(l); + protected void pageBeginMoving() { + 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); } } + protected void pageEndMoving() { + clearChildrenCache(); + } + + @Override + protected void notifyPageSwitchListener() { + super.notifyPageSwitchListener(); + + if (mPreviousIndicator != null) { + // if we know the next page, we show the indication for it right away; it looks + // weird if the indicators are lagging + int page = mNextPage; + if (page == INVALID_PAGE) { + page = mCurrentPage; + } + mPreviousIndicator.setLevel(page); + mNextIndicator.setLevel(page); + } + Launcher.setScreen(mCurrentPage); + }; + private void updateWallpaperOffset() { updateWallpaperOffset(getChildAt(getChildCount() - 1).getRight() - (mRight - mLeft)); } @@ -511,86 +424,6 @@ public class Workspace extends ViewGroup } } - @Override - public void scrollTo(int x, int y) { - super.scrollTo(x, y); - mTouchX = x; - mSmoothingTime = System.nanoTime() / NANOTIME_DIV; - } - - @Override - public void computeScroll() { - if (mScroller.computeScrollOffset()) { - mTouchX = mScrollX = mScroller.getCurrX(); - mSmoothingTime = System.nanoTime() / NANOTIME_DIV; - mScrollY = mScroller.getCurrY(); - updateWallpaperOffset(); - postInvalidate(); - } else if (mNextScreen != INVALID_SCREEN) { - mCurrentScreen = Math.max(0, Math.min(mNextScreen, getChildCount() - 1)); - if (mPreviousIndicator != null) { - mPreviousIndicator.setLevel(mCurrentScreen); - mNextIndicator.setLevel(mCurrentScreen); - } - Launcher.setScreen(mCurrentScreen); - mNextScreen = INVALID_SCREEN; - clearChildrenCache(); - } else if (mTouchState == TOUCH_STATE_SCROLLING) { - final float now = System.nanoTime() / NANOTIME_DIV; - final float e = (float) Math.exp((now - mSmoothingTime) / SMOOTHING_CONSTANT); - final float dx = mTouchX - mScrollX; - mScrollX += dx * e; - mSmoothingTime = now; - - // Keep generating points as long as we're more than 1px away from the target - if (dx > 1.f || dx < -1.f) { - updateWallpaperOffset(); - postInvalidate(); - } - } - } - - @Override - protected void dispatchDraw(Canvas canvas) { - boolean restore = false; - int restoreCount = 0; - - // ViewGroup.dispatchDraw() supports many features we don't need: - // clip to padding, layout animation, animation listener, disappearing - // 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; - - // if the screens are all small, we need to draw all the screens since - // they're most likely all visible - if (mIsSmall) { - final int screenCount = getChildCount(); - for (int i = 0; i < screenCount; i++) { - CellLayout cl = (CellLayout)getChildAt(i); - drawChild(canvas, cl, getDrawingTime()); - } - } else if (fastDraw) { - // If we are not scrolling or flinging, draw only the current screen - drawChild(canvas, getChildAt(mCurrentScreen), getDrawingTime()); - } else { - final long drawingTime = getDrawingTime(); - final float scrollPos = (float) mScrollX / getWidth(); - final int leftScreen = (int) scrollPos; - final int rightScreen = leftScreen + 1; - if (leftScreen >= 0) { - drawChild(canvas, getChildAt(leftScreen), drawingTime); - } - if (scrollPos != leftScreen && rightScreen < getChildCount()) { - drawChild(canvas, getChildAt(rightScreen), drawingTime); - } - } - - if (restore) { - canvas.restoreToCount(restoreCount); - } - } - protected void onAttachedToWindow() { super.onAttachedToWindow(); computeScroll(); @@ -598,49 +431,8 @@ public class Workspace extends ViewGroup } @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - - final int width = MeasureSpec.getSize(widthMeasureSpec); - final int widthMode = MeasureSpec.getMode(widthMeasureSpec); - if (widthMode != MeasureSpec.EXACTLY) { - throw new IllegalStateException("Workspace can only be used in EXACTLY mode."); - } - - final int heightMode = MeasureSpec.getMode(heightMeasureSpec); - if (heightMode != MeasureSpec.EXACTLY) { - throw new IllegalStateException("Workspace can only be used in EXACTLY mode."); - } - - // The children are given the same width and height as the workspace - final int screenCount = getChildCount(); - for (int i = 0; i < screenCount; i++) { - getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); - } - - if (mFirstLayout) { - setHorizontalScrollBarEnabled(false); - setCurrentScreen(mCurrentScreen, false, width); - setHorizontalScrollBarEnabled(true); - } - } - - @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - if (mFirstLayout) { - mFirstLayout = false; - } - int childLeft = 0; - final int screenCount = getChildCount(); - for (int i = 0; i < screenCount; i++) { - final View child = getChildAt(i); - if (child.getVisibility() != View.GONE) { - final int childWidth = child.getMeasuredWidth(); - child.layout(childLeft, 0, - childLeft + childWidth, child.getMeasuredHeight()); - childLeft += childWidth; - } - } + super.onLayout(changed, left, top, right, bottom); // 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 @@ -652,18 +444,27 @@ public class Workspace extends ViewGroup if (LauncherApplication.isInPlaceRotationEnabled()) { // When the device is rotated, the scroll position of the current screen // needs to be refreshed - setCurrentScreen(getCurrentScreen()); + setCurrentPage(getCurrentPage()); } } @Override - public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) { - int screen = indexOfChild(child); - if (screen != mCurrentScreen || !mScroller.isFinished()) { - snapToScreen(screen); - return true; + protected void dispatchDraw(Canvas canvas) { + if (mIsSmall) { + // Draw all the workspaces if we're small + final int pageCount = getChildCount(); + final long drawingTime = getDrawingTime(); + for (int i = 0; i < pageCount; i++) { + final View page = (View) getChildAt(i); + + if (page.getAlpha() != 1.0f) { + page.setAlpha(1.0f); + } + drawChild(canvas, page, drawingTime); + } + } else { + super.dispatchDraw(canvas); } - return false; } @Override @@ -673,51 +474,20 @@ public class Workspace extends ViewGroup if (openFolder != null) { return openFolder.requestFocus(direction, previouslyFocusedRect); } else { - int focusableScreen; - if (mNextScreen != INVALID_SCREEN) { - focusableScreen = mNextScreen; - } else { - focusableScreen = mCurrentScreen; - } - getChildAt(focusableScreen).requestFocus(direction, previouslyFocusedRect); + return super.onRequestFocusInDescendants(direction, previouslyFocusedRect); } } return false; } @Override - public boolean dispatchUnhandledMove(View focused, int direction) { - if (direction == View.FOCUS_LEFT) { - if (getCurrentScreen() > 0) { - snapToScreen(getCurrentScreen() - 1); - return true; - } - } else if (direction == View.FOCUS_RIGHT) { - if (getCurrentScreen() < getChildCount() - 1) { - snapToScreen(getCurrentScreen() + 1); - return true; - } - } - return super.dispatchUnhandledMove(focused, direction); - } - - @Override public void addFocusables(ArrayList<View> views, int direction, int focusableMode) { if (!mLauncher.isAllAppsVisible()) { final Folder openFolder = getOpenFolder(); - if (openFolder == null) { - getChildAt(mCurrentScreen).addFocusables(views, direction); - if (direction == View.FOCUS_LEFT) { - if (mCurrentScreen > 0) { - getChildAt(mCurrentScreen - 1).addFocusables(views, direction); - } - } else if (direction == View.FOCUS_RIGHT) { - if (mCurrentScreen < getChildCount() - 1) { - getChildAt(mCurrentScreen + 1).addFocusables(views, direction); - } - } - } else { + if (openFolder != null) { openFolder.addFocusables(views, direction); + } else { + super.addFocusables(views, direction, focusableMode); } } } @@ -734,213 +504,19 @@ public class Workspace extends ViewGroup return super.dispatchTouchEvent(ev); } - /** - * {@inheritDoc} - */ - @Override - public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { - if (disallowIntercept) { - // We need to make sure to cancel our long press if - // a scrollable widget takes over touch events - final View currentScreen = getChildAt(mCurrentScreen); - currentScreen.cancelLongPress(); - } - super.requestDisallowInterceptTouchEvent(disallowIntercept); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - final boolean allAppsVisible = mLauncher.isAllAppsVisible(); - - // (In XLarge mode, the workspace is shrunken below all apps, and responds to taps - // ie when you click on a mini-screen, it zooms back to that screen) - if (!LauncherApplication.isScreenXLarge() && allAppsVisible) { - return false; // We don't want the events. Let them fall through to the all apps view. - } - - /* - * This method JUST determines whether we want to intercept the motion. - * If we return true, onTouchEvent will be called and we do the actual - * scrolling there. - */ - - /* - * Shortcut the most recurring case: the user is in the dragging - * state and he is moving his finger. We want to intercept this - * motion. - */ - final int action = ev.getAction(); - if ((action == MotionEvent.ACTION_MOVE) && (mTouchState != TOUCH_STATE_REST)) { - return true; - } - - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - mVelocityTracker.addMovement(ev); - - switch (action & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_MOVE: { - /* - * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check - * whether the user has moved far enough from his original down touch. - */ - - /* - * Locally do absolute value. mLastMotionX is set to the y value - * of the down event. - */ - final int pointerIndex = ev.findPointerIndex(mActivePointerId); - final float x = ev.getX(pointerIndex); - final float y = ev.getY(pointerIndex); - final int xDiff = (int) Math.abs(x - mLastMotionX); - final int yDiff = (int) Math.abs(y - mLastMotionY); - - final int touchSlop = mTouchSlop; - boolean xMoved = xDiff > touchSlop; - boolean yMoved = yDiff > touchSlop; - - if (xMoved || yMoved) { - - if (xMoved) { - // Scroll if the user moved far enough along the X axis - mTouchState = TOUCH_STATE_SCROLLING; - mLastMotionX = x; - mTouchX = mScrollX; - mSmoothingTime = System.nanoTime() / NANOTIME_DIV; - enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1); - } - // Either way, cancel any pending longpress - if (mAllowLongPress) { - mAllowLongPress = false; - // Try canceling the long press. It could also have been scheduled - // by a distant descendant, so use the mAllowLongPress flag to block - // everything - final View currentScreen = getChildAt(mCurrentScreen); - currentScreen.cancelLongPress(); - } - } - break; - } - - case MotionEvent.ACTION_DOWN: { - final float x = ev.getX(); - final float y = ev.getY(); - // Remember location of down touch - mLastMotionX = x; - mLastMotionY = y; - mActivePointerId = ev.getPointerId(0); - mAllowLongPress = true; - - /* - * If being flinged and user touches the screen, initiate drag; - * otherwise don't. mScroller.isFinished should be false when - * being flinged. - */ - mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST : TOUCH_STATE_SCROLLING; - break; - } - - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - - if (mTouchState != TOUCH_STATE_SCROLLING) { - final CellLayout currentScreen = (CellLayout)getChildAt(mCurrentScreen); - if (!currentScreen.lastDownOnOccupiedCell()) { - getLocationOnScreen(mTempCell); - // Send a tap to the wallpaper if the last down was on empty space - final int pointerIndex = ev.findPointerIndex(mActivePointerId); - mWallpaperManager.sendWallpaperCommand(getWindowToken(), - "android.wallpaper.tap", - mTempCell[0] + (int) ev.getX(pointerIndex), - mTempCell[1] + (int) ev.getY(pointerIndex), 0, null); - } - } - - // Release the drag - clearChildrenCache(); - mTouchState = TOUCH_STATE_REST; - mActivePointerId = INVALID_POINTER; - mAllowLongPress = false; - - if (mVelocityTracker != null) { - mVelocityTracker.recycle(); - mVelocityTracker = null; - } - - break; - - case MotionEvent.ACTION_POINTER_UP: - onSecondaryPointerUp(ev); - break; - } - - /* - * The only time we want to intercept motion events is if we are in the - * drag mode. - */ - return mTouchState != TOUCH_STATE_REST; - } - - private void onSecondaryPointerUp(MotionEvent ev) { - final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> - MotionEvent.ACTION_POINTER_INDEX_SHIFT; - final int pointerId = ev.getPointerId(pointerIndex); - if (pointerId == mActivePointerId) { - // This was our active pointer going up. Choose a new - // active pointer and adjust accordingly. - // TODO: Make this decision more intelligent. - final int newPointerIndex = pointerIndex == 0 ? 1 : 0; - mLastMotionX = ev.getX(newPointerIndex); - mLastMotionY = ev.getY(newPointerIndex); - mActivePointerId = ev.getPointerId(newPointerIndex); - if (mVelocityTracker != null) { - mVelocityTracker.clear(); - } - } - } - - /** - * If one of our descendant views decides that it could be focused now, only - * pass that along if it's on the current screen. - * - * This happens when live folders requery, and if they're off screen, they - * end up calling requestFocus, which pulls it on screen. - */ - @Override - public void focusableViewAvailable(View focused) { - View current = getChildAt(mCurrentScreen); - View v = focused; - while (true) { - if (v == current) { - super.focusableViewAvailable(focused); - return; - } - if (v == this) { - return; - } - ViewParent parent = v.getParent(); - if (parent instanceof View) { - v = (View) v.getParent(); - } else { - return; - } - } - } - - void enableChildrenCache(int fromScreen, int toScreen) { - if (fromScreen > toScreen) { - final int temp = fromScreen; - fromScreen = toScreen; - toScreen = temp; + void enableChildrenCache(int fromPage, int toPage) { + if (fromPage > toPage) { + final int temp = fromPage; + fromPage = toPage; + toPage = temp; } final int screenCount = getChildCount(); - fromScreen = Math.max(fromScreen, 0); - toScreen = Math.min(toScreen, screenCount - 1); + fromPage = Math.max(fromPage, 0); + toPage = Math.min(toPage, screenCount - 1); - for (int i = fromScreen; i <= toScreen; i++) { + for (int i = fromPage; i <= toPage; i++) { final CellLayout layout = (CellLayout) getChildAt(i); layout.setChildrenDrawnWithCacheEnabled(true); layout.setChildrenDrawingCacheEnabled(true); @@ -962,105 +538,11 @@ public class Workspace extends ViewGroup if (!mScroller.isFinished()) { mScroller.abortAnimation(); } - snapToScreen(mCurrentScreen); + snapToPage(mCurrentPage); return false; // We don't want the events. Let them fall through to the all apps view. } - if (mVelocityTracker == null) { - mVelocityTracker = VelocityTracker.obtain(); - } - mVelocityTracker.addMovement(ev); - - final int action = ev.getAction(); - - switch (action & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - /* - * If being flinged and user touches, stop the fling. isFinished - * will be false if being flinged. - */ - if (!mScroller.isFinished()) { - mScroller.abortAnimation(); - } - - // Remember where the motion event started - mLastMotionX = ev.getX(); - mActivePointerId = ev.getPointerId(0); - if (mTouchState == TOUCH_STATE_SCROLLING) { - enableChildrenCache(mCurrentScreen - 1, mCurrentScreen + 1); - } - break; - case MotionEvent.ACTION_MOVE: - if (mTouchState == TOUCH_STATE_SCROLLING) { - // Scroll to follow the motion event - final int pointerIndex = ev.findPointerIndex(mActivePointerId); - final float x = ev.getX(pointerIndex); - final float deltaX = mLastMotionX - x; - mLastMotionX = x; - - if (deltaX < 0) { - if (mTouchX > 0) { - mTouchX += Math.max(-mTouchX, deltaX); - mSmoothingTime = System.nanoTime() / NANOTIME_DIV; - invalidate(); - } - } else if (deltaX > 0) { - final float availableToScroll = getChildAt(getChildCount() - 1).getRight() - - mTouchX - getWidth(); - if (availableToScroll > 0) { - mTouchX += Math.min(availableToScroll, deltaX); - mSmoothingTime = System.nanoTime() / NANOTIME_DIV; - invalidate(); - } - } else { - awakenScrollBars(); - } - } - break; - case MotionEvent.ACTION_UP: - if (mTouchState == TOUCH_STATE_SCROLLING) { - final VelocityTracker velocityTracker = mVelocityTracker; - velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); - final int velocityX = (int) velocityTracker.getXVelocity(mActivePointerId); - - final int screenWidth = getWidth(); - final int whichScreen = (mScrollX + (screenWidth / 2)) / screenWidth; - final float scrolledPos = (float) mScrollX / screenWidth; - - if (velocityX > SNAP_VELOCITY && mCurrentScreen > 0) { - // Fling hard enough to move left. - // Don't fling across more than one screen at a time. - final int bound = scrolledPos < whichScreen ? - mCurrentScreen - 1 : mCurrentScreen; - snapToScreen(Math.min(whichScreen, bound), velocityX, true); - } else if (velocityX < -SNAP_VELOCITY && mCurrentScreen < getChildCount() - 1) { - // Fling hard enough to move right - // Don't fling across more than one screen at a time. - final int bound = scrolledPos > whichScreen ? - mCurrentScreen + 1 : mCurrentScreen; - snapToScreen(Math.max(whichScreen, bound), velocityX, true); - } else { - snapToScreen(whichScreen, 0, true); - } - - if (mVelocityTracker != null) { - mVelocityTracker.recycle(); - mVelocityTracker = null; - } - } - mTouchState = TOUCH_STATE_REST; - mActivePointerId = INVALID_POINTER; - break; - case MotionEvent.ACTION_CANCEL: - mTouchState = TOUCH_STATE_REST; - mActivePointerId = INVALID_POINTER; - break; - case MotionEvent.ACTION_POINTER_UP: - onSecondaryPointerUp(ev); - break; - } - - return true; + return super.onTouchEvent(ev); } public boolean isSmall() { @@ -1068,11 +550,11 @@ public class Workspace extends ViewGroup } void shrinkToTop(boolean animated) { - shrink(SHRINK_TO_TOP, animated); + shrink(ShrinkPosition.SHRINK_TO_TOP, animated); } void shrinkToMiddle() { - shrink(SHRINK_TO_MIDDLE, true); + shrink(ShrinkPosition.SHRINK_TO_MIDDLE, true); } void shrinkToBottom() { @@ -1087,35 +569,40 @@ public class Workspace extends ViewGroup // to get our width so we can layout the mini-screen views correctly mWaitingToShrinkToBottom = true; } else { - shrink(SHRINK_TO_BOTTOM, animated); + shrink(ShrinkPosition.SHRINK_TO_BOTTOM, animated); } } // we use this to shrink the workspace for the all apps view and the customize view - private void shrink(int shrinkPosition, boolean animated) { + private void shrink(ShrinkPosition shrinkPosition, boolean animated) { mIsSmall = true; final Resources res = getResources(); final int screenWidth = getWidth(); final int screenHeight = getHeight(); - final int scaledScreenWidth = (int) (SHRINK_FACTOR * screenWidth); - final int scaledScreenHeight = (int) (SHRINK_FACTOR * screenHeight); + + // Making the assumption that all pages have the same width as the 0th + final int pageWidth = getChildAt(0).getMeasuredWidth(); + final int pageHeight = getChildAt(0).getMeasuredHeight(); + + final int scaledPageWidth = (int) (SHRINK_FACTOR * pageWidth); + final int scaledPageHeight = (int) (SHRINK_FACTOR * pageHeight); final float scaledSpacing = res.getDimension(R.dimen.smallScreenSpacing); final int screenCount = getChildCount(); - float totalWidth = screenCount * scaledScreenWidth + (screenCount - 1) * scaledSpacing; + float totalWidth = screenCount * scaledPageWidth + (screenCount - 1) * scaledSpacing; float newY = getResources().getDimension(R.dimen.smallScreenVerticalMargin); - if (shrinkPosition == SHRINK_TO_BOTTOM) { - newY = screenHeight - newY - scaledScreenHeight; - } else if (shrinkPosition == SHRINK_TO_MIDDLE) { - newY = screenHeight / 2 - scaledScreenHeight / 2; + if (shrinkPosition == ShrinkPosition.SHRINK_TO_BOTTOM) { + newY = screenHeight - newY - scaledPageHeight; + } else if (shrinkPosition == ShrinkPosition.SHRINK_TO_MIDDLE) { + newY = screenHeight / 2 - scaledPageHeight / 2; } // We animate all the screens to the centered position in workspace // At the same time, the screens become greyed/dimmed // newX is initialized to the left-most position of the centered screens - float newX = (mCurrentScreen + 1) * screenWidth - screenWidth / 2 - totalWidth / 2; + float newX = mScroller.getFinalX() + screenWidth / 2 - totalWidth / 2; for (int i = 0; i < screenCount; i++) { CellLayout cl = (CellLayout) getChildAt(i); cl.setPivotX(0.0f); @@ -1136,7 +623,7 @@ public class Workspace extends ViewGroup cl.setDimmedBitmapAlpha(1.0f); } // increment newX for the next screen - newX += scaledScreenWidth + scaledSpacing; + newX += scaledPageWidth + scaledSpacing; cl.setOnInterceptTouchListener(this); } setChildrenDrawnWithCacheEnabled(true); @@ -1144,29 +631,29 @@ public class Workspace extends ViewGroup // We call this when we trigger an unshrink by clicking on the CellLayout cl private void unshrink(CellLayout clThatWasClicked) { - int newCurrentScreen = mCurrentScreen; + int newCurrentPage = mCurrentPage; final int screenCount = getChildCount(); for (int i = 0; i < screenCount; i++) { if (getChildAt(i) == clThatWasClicked) { - newCurrentScreen = i; + newCurrentPage = i; } } - unshrink(newCurrentScreen); + unshrink(newCurrentPage); } - private void unshrink(int newCurrentScreen) { + private void unshrink(int newCurrentPage) { if (mIsSmall) { - int delta = (newCurrentScreen - mCurrentScreen)*getWidth(); + int delta = (newCurrentPage - mCurrentPage)*getWidth(); final int screenCount = getChildCount(); for (int i = 0; i < screenCount; i++) { CellLayout cl = (CellLayout) getChildAt(i); cl.setX(cl.getX() + delta); } - mScrollX = newCurrentScreen * getWidth(); - + snapToPage(newCurrentPage); unshrink(); - setCurrentScreen(newCurrentScreen); + + setCurrentPage(newCurrentPage); } } @@ -1186,11 +673,11 @@ public class Workspace extends ViewGroup cl.setPivotY(0.0f); if (animated) { s.playTogether( - new PropertyAnimator(duration, cl, "translationX", 0.0f), - new PropertyAnimator(duration, cl, "translationY", 0.0f), - new PropertyAnimator(duration, cl, "scaleX", 1.0f), - new PropertyAnimator(duration, cl, "scaleY", 1.0f), - new PropertyAnimator(duration, cl, "dimmedBitmapAlpha", 0.0f)); + new PropertyAnimator<Float>(duration, cl, "translationX", 0.0f), + new PropertyAnimator<Float>(duration, cl, "translationY", 0.0f), + new PropertyAnimator<Float>(duration, cl, "scaleX", 1.0f), + new PropertyAnimator<Float>(duration, cl, "scaleY", 1.0f), + new PropertyAnimator<Float>(duration, cl, "dimmedBitmapAlpha", 0.0f)); } else { cl.setTranslationX(0.0f); cl.setTranslationY(0.0f); @@ -1204,58 +691,6 @@ public class Workspace extends ViewGroup } } - void snapToScreen(int whichScreen) { - snapToScreen(whichScreen, 0, false); - } - - private void snapToScreen(int whichScreen, int velocity, boolean settle) { - // if (!mScroller.isFinished()) return; - - whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1)); - - enableChildrenCache(mCurrentScreen, whichScreen); - - mNextScreen = whichScreen; - - if (mPreviousIndicator != null) { - mPreviousIndicator.setLevel(mNextScreen); - mNextIndicator.setLevel(mNextScreen); - } - - View focusedChild = getFocusedChild(); - if (focusedChild != null && whichScreen != mCurrentScreen && - focusedChild == getChildAt(mCurrentScreen)) { - focusedChild.clearFocus(); - } - - final int screenDelta = Math.max(1, Math.abs(whichScreen - mCurrentScreen)); - final int newX = whichScreen * getWidth(); - final int delta = newX - mScrollX; - int duration = (screenDelta + 1) * 100; - - if (!mScroller.isFinished()) { - mScroller.abortAnimation(); - } - - if (settle) { - mScrollInterpolator.setDistance(screenDelta); - } else { - mScrollInterpolator.disableSettle(); - } - - velocity = Math.abs(velocity); - if (velocity > 0) { - duration += (duration / (velocity / BASELINE_FLING_VELOCITY)) - * FLING_VELOCITY_INFLUENCE; - } else { - duration += 100; - } - - awakenScrollBars(duration); - mScroller.startScroll(mScrollX, 0, delta, 0, duration); - invalidate(); - } - void startDrag(CellLayout.CellInfo cellInfo) { View child = cellInfo.cell; @@ -1265,32 +700,15 @@ public class Workspace extends ViewGroup } mDragInfo = cellInfo; - mDragInfo.screen = mCurrentScreen; + mDragInfo.screen = mCurrentPage; - CellLayout current = ((CellLayout) getChildAt(mCurrentScreen)); + CellLayout current = ((CellLayout) getChildAt(mCurrentPage)); current.onDragChild(child); mDragController.startDrag(child, this, child.getTag(), DragController.DRAG_ACTION_MOVE); invalidate(); } - @Override - protected Parcelable onSaveInstanceState() { - final SavedState state = new SavedState(super.onSaveInstanceState()); - state.currentScreen = mCurrentScreen; - return state; - } - - @Override - protected void onRestoreInstanceState(Parcelable state) { - SavedState savedState = (SavedState) state; - super.onRestoreInstanceState(savedState.getSuperState()); - if (savedState.currentScreen != -1) { - setCurrentScreen(savedState.currentScreen, false); - Launcher.setScreen(mCurrentScreen); - } - } - void addApplicationShortcut(ShortcutInfo info, CellLayout.CellInfo cellInfo) { addApplicationShortcut(info, cellInfo, false); } @@ -1319,7 +737,7 @@ public class Workspace extends ViewGroup // dragRegionLeft/Top to xOffset and yOffset localBottomRightXY[0] = originX + dragView.getDragRegionWidth(); localBottomRightXY[1] = originY + dragView.getDragRegionHeight(); - cellLayout = findMatchingScreenForDragOver(localXY, localBottomRightXY); + cellLayout = findMatchingPageForDragOver(localXY, localBottomRightXY); if (cellLayout == null) { // cancel the drag if we're not over a mini-screen at time of drop // TODO: maybe add a nice fade here? @@ -1335,7 +753,7 @@ public class Workspace extends ViewGroup // Move internally if (mDragInfo != null) { final View cell = mDragInfo.cell; - int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen; + int index = mScroller.isFinished() ? mCurrentPage : mNextPage; if (index != mDragInfo.screen) { final CellLayout originalCellLayout = (CellLayout) getChildAt(mDragInfo.screen); originalCellLayout.removeView(cell); @@ -1406,7 +824,7 @@ public class Workspace extends ViewGroup // This method will see which mini-screen is most overlapped by the item being dragged, and // return it. It will also transform the parameters xy and bottomRightXy into the local // coordinate space of the returned screen - private CellLayout findMatchingScreenForDragOver(float[] xy, float[] bottomRightXy) { + private CellLayout findMatchingPageForDragOver(float[] xy, float[] bottomRightXy) { float x = xy[0]; float y = xy[1]; float right = bottomRightXy[0]; @@ -1504,7 +922,7 @@ public class Workspace extends ViewGroup localBottomRightXY[0] = originX + dragView.getDragRegionWidth(); localBottomRightXY[1] = originY + dragView.getDragRegionHeight(); - currentLayout = findMatchingScreenForDragOver(localXY, localBottomRightXY); + currentLayout = findMatchingPageForDragOver(localXY, localBottomRightXY); if (currentLayout != null) { currentLayout.setHover(true); } @@ -1575,7 +993,7 @@ public class Workspace extends ViewGroup break; case LauncherSettings.Favorites.ITEM_TYPE_USER_FOLDER: view = FolderIcon.fromXml(R.layout.folder_icon, mLauncher, - (ViewGroup) getChildAt(mCurrentScreen), + (ViewGroup) getChildAt(mCurrentPage), ((UserFolderInfo) info)); break; case LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET: @@ -1602,7 +1020,7 @@ public class Workspace extends ViewGroup CellLayout.LayoutParams lp = (CellLayout.LayoutParams) view.getLayoutParams(); LauncherModel.addOrMoveItemInDatabase(mLauncher, info, - LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentScreen, + LauncherSettings.Favorites.CONTAINER_DESKTOP, mCurrentPage, lp.cellX, lp.cellY); } } @@ -1612,7 +1030,7 @@ public class Workspace extends ViewGroup * screen while a scroll is in progress. */ private CellLayout getCurrentDropLayout() { - int index = mScroller.isFinished() ? mCurrentScreen : mNextScreen; + int index = mScroller.isFinished() ? mCurrentPage : mNextPage; return (CellLayout) getChildAt(index); } @@ -1689,7 +1107,7 @@ public class Workspace extends ViewGroup * Estimate the size that a child with the given dimensions will take in the current screen. */ void estimateChildSize(int minWidth, int minHeight, int[] result) { - ((CellLayout)getChildAt(mCurrentScreen)).estimateChildSize(minWidth, minHeight, result); + ((CellLayout)getChildAt(mCurrentPage)).estimateChildSize(minWidth, minHeight, result); } void setLauncher(Launcher launcher) { @@ -1720,42 +1138,24 @@ public class Workspace extends ViewGroup mDragInfo = null; } + @Override + protected void onRestoreInstanceState(Parcelable state) { + super.onRestoreInstanceState(state); + Launcher.setScreen(mCurrentPage); + } + + @Override public void scrollLeft() { if (!mIsSmall) { - if (mScroller.isFinished()) { - if (mCurrentScreen > 0) - snapToScreen(mCurrentScreen - 1); - } else { - if (mNextScreen > 0) - snapToScreen(mNextScreen - 1); - } + super.scrollLeft(); } } + @Override public void scrollRight() { if (!mIsSmall) { - if (mScroller.isFinished()) { - if (mCurrentScreen < getChildCount() - 1) - snapToScreen(mCurrentScreen + 1); - } else { - if (mNextScreen < getChildCount() - 1) - snapToScreen(mNextScreen + 1); - } - } - } - - public int getScreenForView(View v) { - int result = -1; - if (v != null) { - ViewParent vp = v.getParent(); - final int screenCount = getChildCount(); - for (int i = 0; i < screenCount; i++) { - if (vp == getChildAt(i)) { - return i; - } - } + super.scrollRight(); } - return result; } public Folder getFolderForTag(Object tag) { @@ -1792,20 +1192,6 @@ public class Workspace extends ViewGroup return null; } - /** - * @return True is long presses are still allowed for the current touch - */ - public boolean allowLongPress() { - return mAllowLongPress; - } - - /** - * Set true to allow long-press events to be triggered, usually checked by - * {@link Launcher} to accept or block dpad-initiated long-presses. - */ - public void setAllowLongPress(boolean allowLongPress) { - mAllowLongPress = allowLongPress; - } void removeItems(final ArrayList<ApplicationInfo> apps) { final int screenCount = getChildCount(); @@ -1964,50 +1350,29 @@ public class Workspace extends ViewGroup void moveToDefaultScreen(boolean animate) { if (animate) { if (mIsSmall) { - unshrink(mDefaultScreen); + unshrink(mDefaultPage); } else { - snapToScreen(mDefaultScreen); + snapToPage(mDefaultPage); } } else { - setCurrentScreen(mDefaultScreen); + setCurrentPage(mDefaultPage); } - getChildAt(mDefaultScreen).requestFocus(); + getChildAt(mDefaultPage).requestFocus(); } void setIndicators(Drawable previous, Drawable next) { mPreviousIndicator = previous; mNextIndicator = next; - previous.setLevel(mCurrentScreen); - next.setLevel(mCurrentScreen); + previous.setLevel(mCurrentPage); + next.setLevel(mCurrentPage); } - public static class SavedState extends BaseSavedState { - int currentScreen = -1; - - SavedState(Parcelable superState) { - super(superState); - } - - private SavedState(Parcel in) { - super(in); - currentScreen = in.readInt(); - } - - @Override - public void writeToParcel(Parcel out, int flags) { - super.writeToParcel(out, flags); - out.writeInt(currentScreen); - } - - public static final Parcelable.Creator<SavedState> CREATOR = - new Parcelable.Creator<SavedState>() { - public SavedState createFromParcel(Parcel in) { - return new SavedState(in); - } + @Override + public void syncPages() { + } - public SavedState[] newArray(int size) { - return new SavedState[size]; - } - }; + @Override + public void syncPageItems(int page) { } + } |