From 76fc085d28178a5d4fb3787ede956281a2cc3179 Mon Sep 17 00:00:00 2001 From: Adam Cohen Date: Fri, 17 Jun 2011 13:26:23 -0700 Subject: New folder visualization, renaming, staggering reorder Change-Id: I62963d225e6ea5d2ec9d8ebc8a6d73099f5d6c7f --- src/com/android/launcher2/BubbleTextView.java | 10 +- src/com/android/launcher2/CellLayout.java | 9 +- src/com/android/launcher2/CellLayoutChildren.java | 2 +- src/com/android/launcher2/DragLayer.java | 41 +++++-- src/com/android/launcher2/FastBitmapDrawable.java | 4 + src/com/android/launcher2/Folder.java | 130 +++++++++++++++++++--- src/com/android/launcher2/FolderIcon.java | 126 ++++++++++++--------- src/com/android/launcher2/FolderInfo.java | 8 ++ src/com/android/launcher2/Launcher.java | 8 +- src/com/android/launcher2/PagedView.java | 2 +- src/com/android/launcher2/Workspace.java | 60 +++++----- 11 files changed, 277 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/com/android/launcher2/BubbleTextView.java b/src/com/android/launcher2/BubbleTextView.java index 703b3a8cb..8c0c27ca2 100644 --- a/src/com/android/launcher2/BubbleTextView.java +++ b/src/com/android/launcher2/BubbleTextView.java @@ -262,10 +262,12 @@ public class BubbleTextView extends TextView implements VisibilityChangedBroadca } void setCellLayoutPressedOrFocusedIcon() { - CellLayoutChildren parent = (CellLayoutChildren) getParent(); - if (parent != null) { - CellLayout layout = (CellLayout) parent.getParent(); - layout.setPressedOrFocusedIcon((mPressedOrFocusedBackground != null) ? this : null); + if (getParent() instanceof CellLayoutChildren) { + CellLayoutChildren parent = (CellLayoutChildren) getParent(); + if (parent != null) { + CellLayout layout = (CellLayout) parent.getParent(); + layout.setPressedOrFocusedIcon((mPressedOrFocusedBackground != null) ? this : null); + } } } diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index a9ba88d94..c1aa2d589 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -298,6 +298,7 @@ public class CellLayout extends ViewGroup { mCountX = x; mCountY = y; mOccupied = new boolean[mCountX][mCountY]; + requestLayout(); } private void invalidateBubbleTextView(BubbleTextView icon) { @@ -971,7 +972,8 @@ public class CellLayout extends ViewGroup { return mChildren.getChildAt(x, y); } - public boolean animateChildToPosition(final View child, int cellX, int cellY, int duration) { + public boolean animateChildToPosition(final View child, int cellX, int cellY, int duration, + int delay) { CellLayoutChildren clc = getChildrenLayout(); if (clc.indexOfChild(child) != -1 && !mOccupied[cellX][cellY]) { final LayoutParams lp = (LayoutParams) child.getLayoutParams(); @@ -996,6 +998,10 @@ public class CellLayout extends ViewGroup { int newX = lp.x; int newY = lp.y; + lp.x = oldX; + lp.y = oldY; + child.requestLayout(); + PropertyValuesHolder x = PropertyValuesHolder.ofInt("x", oldX, newX); PropertyValuesHolder y = PropertyValuesHolder.ofInt("y", oldY, newY); ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(lp, x, y); @@ -1023,6 +1029,7 @@ public class CellLayout extends ViewGroup { cancelled = true; } }); + oa.setStartDelay(delay); oa.start(); return true; } diff --git a/src/com/android/launcher2/CellLayoutChildren.java b/src/com/android/launcher2/CellLayoutChildren.java index 6e78885de..1caecc001 100644 --- a/src/com/android/launcher2/CellLayoutChildren.java +++ b/src/com/android/launcher2/CellLayoutChildren.java @@ -83,6 +83,7 @@ public class CellLayoutChildren extends ViewGroup { lp.setup(mCellWidth, mCellHeight, mWidthGap, mHeightGap); } + public void measureChild(View child) { final int cellWidth = mCellWidth; final int cellHeight = mCellHeight; @@ -92,7 +93,6 @@ public class CellLayoutChildren extends ViewGroup { int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY); int childheightMeasureSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY); - child.measure(childWidthMeasureSpec, childheightMeasureSpec); } diff --git a/src/com/android/launcher2/DragLayer.java b/src/com/android/launcher2/DragLayer.java index af47bea78..c4d75d6eb 100644 --- a/src/com/android/launcher2/DragLayer.java +++ b/src/com/android/launcher2/DragLayer.java @@ -25,6 +25,7 @@ import android.util.AttributeSet; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.view.ViewParent; import android.widget.FrameLayout; import android.widget.ImageView; @@ -62,13 +63,13 @@ public class DragLayer extends FrameLayout { mLauncher = launcher; mDragController = controller; } - + @Override public boolean dispatchKeyEvent(KeyEvent event) { return mDragController.dispatchKeyEvent(event) || super.dispatchKeyEvent(event); } - private boolean handleTouchDown(MotionEvent ev) { + private boolean handleTouchDown(MotionEvent ev, boolean intercept) { Rect hitRect = new Rect(); int x = (int) ev.getX(); int y = (int) ev.getY(); @@ -85,17 +86,21 @@ public class DragLayer extends FrameLayout { } } } - if (mCurrentFolder != null) { - mCurrentFolder.getHitRect(hitRect); - int[] screenPos = new int[2]; - View parent = (View) mCurrentFolder.getParent(); - if (parent != null) { - parent.getLocationOnScreen(screenPos); - hitRect.offset(screenPos[0], screenPos[1]); + + if (mCurrentFolder != null && intercept) { + if (mCurrentFolder.isEditingName()) { + getDescendantRectRelativeToSelf(mCurrentFolder.getEditTextRegion(), hitRect); if (!hitRect.contains(x, y)) { - mLauncher.closeFolder(); + mCurrentFolder.dismissEditingName(); + return true; } } + + getDescendantRectRelativeToSelf(mCurrentFolder, hitRect); + if (!hitRect.contains(x, y)) { + mLauncher.closeFolder(); + return true; + } } return false; } @@ -103,7 +108,7 @@ public class DragLayer extends FrameLayout { @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { - if (handleTouchDown(ev)) { + if (handleTouchDown(ev, true)) { return true; } } @@ -121,7 +126,7 @@ public class DragLayer extends FrameLayout { if (ev.getAction() == MotionEvent.ACTION_DOWN) { if (ev.getAction() == MotionEvent.ACTION_DOWN) { - if (handleTouchDown(ev)) { + if (handleTouchDown(ev, false)) { return true; } } @@ -143,6 +148,18 @@ public class DragLayer extends FrameLayout { return mDragController.onTouchEvent(ev); } + private void getDescendantRectRelativeToSelf(View descendant, Rect r) { + descendant.getHitRect(r); + + ViewParent viewParent = descendant.getParent(); + while (viewParent instanceof View && viewParent != this) { + final View view = (View)viewParent; + r.offset(view.getLeft() + (int) (view.getTranslationX() + 0.5f) - view.getScrollX(), + view.getTop() + (int) (view.getTranslationY() + 0.5f) - view.getScrollY()); + viewParent = view.getParent(); + } + } + @Override public boolean dispatchUnhandledMove(View focused, int direction) { return mDragController.dispatchUnhandledMove(focused, direction); diff --git a/src/com/android/launcher2/FastBitmapDrawable.java b/src/com/android/launcher2/FastBitmapDrawable.java index 3e75fb6d0..9fa62da4a 100644 --- a/src/com/android/launcher2/FastBitmapDrawable.java +++ b/src/com/android/launcher2/FastBitmapDrawable.java @@ -64,6 +64,10 @@ class FastBitmapDrawable extends Drawable { mPaint.setAlpha(alpha); } + public void setFilterBitmap(boolean filterBitmap) { + mPaint.setFilterBitmap(filterBitmap); + } + public int getAlpha() { return mAlpha; } diff --git a/src/com/android/launcher2/Folder.java b/src/com/android/launcher2/Folder.java index d81183c6b..960fa551c 100644 --- a/src/com/android/launcher2/Folder.java +++ b/src/com/android/launcher2/Folder.java @@ -23,16 +23,22 @@ import android.animation.PropertyValuesHolder; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; import android.content.Context; -import android.graphics.Color; +import android.content.res.Resources; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.util.AttributeSet; +import android.view.ActionMode; +import android.view.KeyEvent; import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; +import android.view.inputmethod.EditorInfo; +import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.LinearLayout; import android.widget.TextView; @@ -48,7 +54,8 @@ import java.util.ArrayList; * Represents a set of icons chosen by the user or generated by the system. */ public class Folder extends LinearLayout implements DragSource, OnItemLongClickListener, - OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget, FolderListener { + OnItemClickListener, OnClickListener, View.OnLongClickListener, DropTarget, FolderListener, + TextView.OnEditorActionListener { protected DragController mDragController; @@ -90,6 +97,11 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL private int[] mEmptyCell = new int[2]; private Alarm mReorderAlarm = new Alarm(); private Alarm mOnExitAlarm = new Alarm(); + private TextView mFolderName; + private int mFolderNameHeight; + + private boolean mIsEditingName = false; + private InputMethodManager mInputMethodManager; /** * Used to inflate the Workspace from XML. @@ -102,10 +114,14 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL setAlwaysDrawnWithCacheEnabled(false); mInflater = LayoutInflater.from(context); mIconCache = ((LauncherApplication)context.getApplicationContext()).getIconCache(); - mExpandDuration = getResources().getInteger(R.integer.config_folderAnimDuration); - mMaxCountX = LauncherModel.getCellCountX() - 1; mMaxCountY = LauncherModel.getCellCountY() - 1; + + mInputMethodManager = (InputMethodManager) + mContext.getSystemService(Context.INPUT_METHOD_SERVICE); + + Resources res = getResources(); + mExpandDuration = res.getInteger(R.integer.config_folderAnimDuration); } @Override @@ -114,8 +130,37 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL mContent = (CellLayout) findViewById(R.id.folder_content); mContent.setGridSize(0, 0); mContent.enableHardwareLayers(); + mFolderName = (TextView) findViewById(R.id.folder_name); + + // We find out how tall the text view wants to be (it is set to wrap_content), so that + // we can allocate the appropriate amount of space for it. + int measureSpec = MeasureSpec.UNSPECIFIED; + mFolderName.measure(measureSpec, measureSpec); + mFolderNameHeight = mFolderName.getMeasuredHeight(); + + // We disable action mode for now since it messes up the view on phones + mFolderName.setCustomSelectionActionModeCallback(mActionModeCallback); + mFolderName.setCursorVisible(false); + mFolderName.setOnEditorActionListener(this); } + private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { + public boolean onActionItemClicked(ActionMode mode, MenuItem item) { + return false; + } + + public boolean onCreateActionMode(ActionMode mode, Menu menu) { + return false; + } + + public void onDestroyActionMode(ActionMode mode) { + } + + public boolean onPrepareActionMode(ActionMode mode, Menu menu) { + return false; + } + }; + public void onItemClick(AdapterView parent, View v, int position, long id) { ShortcutInfo app = (ShortcutInfo) parent.getItemAtPosition(position); int[] pos = new int[2]; @@ -138,6 +183,17 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL } } + private Rect mHitRect = new Rect(); + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mFolderName.getHitRect(mHitRect); + if (mHitRect.contains((int) ev.getX(), (int) ev.getY()) && !mIsEditingName) { + startEditingFolderName(); + } + } + return false; + } + public boolean onLongClick(View v) { Object tag = v.getTag(); if (tag instanceof ShortcutInfo) { @@ -158,13 +214,44 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL mCurrentDragView = v; mContent.removeView(mCurrentDragView); mInfo.remove(item); - } else { - mLauncher.closeFolder(this); - mLauncher.showRenameDialog(mInfo); } return true; } + public boolean isEditingName() { + return mIsEditingName; + } + + public void startEditingFolderName() { + mFolderName.setCursorVisible(true); + mIsEditingName = true; + } + + public void dismissEditingName() { + mInputMethodManager.hideSoftInputFromWindow(getWindowToken(), 0); + doneEditingFolderName(true); + } + + public void doneEditingFolderName(boolean commit) { + mInfo.setTitle(mFolderName.getText()); + LauncherModel.updateItemInDatabase(mLauncher, mInfo); + mFolderName.setCursorVisible(false); + mFolderName.clearFocus(); + mIsEditingName = false; + } + + public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + dismissEditingName(); + return true; + } + return false; + } + + public View getEditTextRegion() { + return mFolderName; + } + public Drawable getDragDrawable() { return mIconDrawable; } @@ -216,12 +303,13 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL // forcing a layout // TODO: find out if this is still necessary mContent.requestLayout(); - requestFocus(); } void onClose() { - final Workspace workspace = mLauncher.getWorkspace(); - workspace.getChildAt(workspace.getCurrentPage()).requestFocus(); + CellLayoutChildren clc = (CellLayoutChildren) getParent(); + final CellLayout cellLayout = (CellLayout) clc.getParent(); + cellLayout.removeViewWithoutMarkingCells(Folder.this); + clearFocus(); } void bind(FolderInfo info) { @@ -234,6 +322,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL } mItemsInvalidated = true; mInfo.addListener(this); + mFolderName.setText(mInfo.title); } /** @@ -322,10 +411,7 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL public void animateClosed() { if (!(getParent() instanceof CellLayoutChildren)) return; - CellLayoutChildren clc = (CellLayoutChildren) getParent(); - final CellLayout cellLayout = (CellLayout) clc.getParent(); ObjectAnimator oa; - if (mMode == PARTIAL_GROW) { PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 0); PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 0.9f); @@ -356,8 +442,8 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL oa.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { + onClose(); onCloseComplete(); - cellLayout.removeViewWithoutMarkingCells(Folder.this); mState = STATE_SMALL; } @Override @@ -438,6 +524,8 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL int startX; int endX; int startY; + int delay = 0; + float delayAmount = 30; if (readingOrderGreaterThan(target, empty)) { wrap = empty[0] >= mContent.getCountX() - 1; startY = wrap ? empty[1] + 1 : empty[1]; @@ -447,9 +535,11 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL for (int x = startX; x <= endX; x++) { View v = mContent.getChildAt(x,y); if (mContent.animateChildToPosition(v, empty[0], empty[1], - REORDER_ANIMATION_DURATION)) { + REORDER_ANIMATION_DURATION, delay)) { empty[0] = x; empty[1] = y; + delay += delayAmount; + delayAmount *= 0.9; } } } @@ -462,9 +552,11 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL for (int x = startX; x >= endX; x--) { View v = mContent.getChildAt(x,y); if (mContent.animateChildToPosition(v, empty[0], empty[1], - REORDER_ANIMATION_DURATION)) { + REORDER_ANIMATION_DURATION, delay)) { empty[0] = x; empty[1] = y; + delay += delayAmount; + delayAmount *= 0.9; } } } @@ -591,7 +683,9 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL CellLayout.LayoutParams lp = (CellLayout.LayoutParams) getLayoutParams(); int width = getPaddingLeft() + getPaddingRight() + mContent.getDesiredWidth(); - int height = getPaddingTop() + getPaddingBottom() + mContent.getDesiredHeight(); + // Technically there is no padding at the bottom, but we add space equal to the padding + // and have to account for that here. + int height = getPaddingTop() + mContent.getDesiredHeight() + mFolderNameHeight; int centerX = iconLp.x + iconLp.width / 2; int centerY = iconLp.y + iconLp.height / 2; @@ -732,6 +826,8 @@ public class Folder extends LinearLayout implements DragSource, OnItemLongClickL public void onItemsChanged() { } + public void onTitleChanged(CharSequence title) { + } public ArrayList getItemsInReadingOrder() { return getItemsInReadingOrder(true); diff --git a/src/com/android/launcher2/FolderIcon.java b/src/com/android/launcher2/FolderIcon.java index 18b242bfa..db3dfe8f2 100644 --- a/src/com/android/launcher2/FolderIcon.java +++ b/src/com/android/launcher2/FolderIcon.java @@ -30,7 +30,8 @@ import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher.R; @@ -42,39 +43,32 @@ import java.util.ArrayList; /** * An icon that can appear on in the workspace representing an {@link UserFolder}. */ -public class FolderIcon extends FrameLayout implements FolderListener { +public class FolderIcon extends LinearLayout implements FolderListener { private Launcher mLauncher; Folder mFolder; FolderInfo mInfo; // The number of icons to display in the - private static final int NUM_ITEMS_IN_PREVIEW = 4; + private static final int NUM_ITEMS_IN_PREVIEW = 3; private static final int CONSUMPTION_ANIMATION_DURATION = 100; // The degree to which the inner ring grows when accepting drop private static final float INNER_RING_GROWTH_FACTOR = 0.1f; - // The degree to which the inner ring is scaled in its natural state - private static final float INNER_RING_BASELINE_SCALE = 1.0f; - - // The degree to which the outer ring grows when accepting drop - private static final float OUTER_RING_BASELINE_SCALE = 0.7f; - // The degree to which the outer ring is scaled in its natural state - private static final float OUTER_RING_GROWTH_FACTOR = 0.3f; + private static final float OUTER_RING_GROWTH_FACTOR = 0.4f; // The amount of vertical spread between items in the stack [0...1] - private static final float PERSPECTIVE_SHIFT_FACTOR = 0.3f; + private static final float PERSPECTIVE_SHIFT_FACTOR = 0.24f; // The degree to which the item in the back of the stack is scaled [0...1] // (0 means it's not scaled at all, 1 means it's scaled to nothing) - private static final float PERSPECTIVE_SCALE_FACTOR = 0.3f; - - // The percentage of the FolderIcons view that will be dedicated to the items preview - private static final float SPACE_PERCENTAGE_FOR_ICONS = 0.8f; + private static final float PERSPECTIVE_SCALE_FACTOR = 0.35f; private int mOriginalWidth = -1; private int mOriginalHeight = -1; + private ImageView mPreviewBackground; + private BubbleTextView mFolderName; FolderRingAnimator mFolderRingAnimator = null; @@ -98,9 +92,10 @@ public class FolderIcon extends FrameLayout implements FolderListener { FolderIcon icon = (FolderIcon) LayoutInflater.from(launcher).inflate(resId, group, false); - final Resources resources = launcher.getResources(); - Drawable d = iconCache.getFullResIcon(resources, R.drawable.portal_ring_inner_holo); - icon.setBackgroundDrawable(d); + icon.mFolderName = (BubbleTextView) icon.findViewById(R.id.folder_name); + icon.mFolderName.setText(folderInfo.title); + icon.mPreviewBackground = (ImageView) icon.findViewById(R.id.preview_background); + icon.setTag(folderInfo); icon.setOnClickListener(launcher); icon.mInfo = folderInfo; @@ -121,31 +116,36 @@ public class FolderIcon extends FrameLayout implements FolderListener { public static class FolderRingAnimator { public int mFolderLocX; public int mFolderLocY; - public float mOuterRingScale; - public float mInnerRingScale; + public float mOuterRingSize; + public float mInnerRingSize; public FolderIcon mFolderIcon = null; private Launcher mLauncher; public Drawable mOuterRingDrawable = null; public Drawable mInnerRingDrawable = null; public static Drawable sSharedOuterRingDrawable = null; public static Drawable sSharedInnerRingDrawable = null; + public static int sPreviewSize = -1; + public static int sPreviewPadding = -1; + private ValueAnimator mAcceptAnimator; private ValueAnimator mNeutralAnimator; public FolderRingAnimator(Launcher launcher, FolderIcon folderIcon) { mLauncher = launcher; mFolderIcon = folderIcon; - mOuterRingDrawable = - launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo); - mInnerRingDrawable = - launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo); + Resources res = launcher.getResources(); + mOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo); + mInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_holo); + + if (sPreviewSize < 0 || sPreviewPadding < 0) { + sPreviewSize = res.getDimensionPixelSize(R.dimen.folder_preview_size); + sPreviewPadding = res.getDimensionPixelSize(R.dimen.folder_preview_padding); + } if (sSharedOuterRingDrawable == null) { - sSharedOuterRingDrawable = - launcher.getResources().getDrawable(R.drawable.portal_ring_outer_holo); + sSharedOuterRingDrawable = res.getDrawable(R.drawable.portal_ring_outer_holo); } if (sSharedInnerRingDrawable == null) { - sSharedInnerRingDrawable = - launcher.getResources().getDrawable(R.drawable.portal_ring_inner_holo); + sSharedInnerRingDrawable = res.getDrawable(R.drawable.portal_ring_inner_holo); } } @@ -164,8 +164,8 @@ public class FolderIcon extends FrameLayout implements FolderListener { mAcceptAnimator.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { final float percent = (Float) animation.getAnimatedValue(); - mOuterRingScale = OUTER_RING_BASELINE_SCALE + percent * OUTER_RING_GROWTH_FACTOR; - mInnerRingScale = INNER_RING_BASELINE_SCALE + percent * INNER_RING_GROWTH_FACTOR; + mOuterRingSize = (1 + percent * OUTER_RING_GROWTH_FACTOR) * sPreviewSize; + mInnerRingSize = (1 + percent * INNER_RING_GROWTH_FACTOR) * sPreviewSize; mLauncher.getWorkspace().invalidate(); if (mFolderIcon != null) { mFolderIcon.invalidate(); @@ -176,7 +176,7 @@ public class FolderIcon extends FrameLayout implements FolderListener { @Override public void onAnimationStart(Animator animation) { if (mFolderIcon != null) { - mFolderIcon.setBackgroundDrawable(null); + mFolderIcon.mPreviewBackground.setVisibility(INVISIBLE); } } }); @@ -192,10 +192,8 @@ public class FolderIcon extends FrameLayout implements FolderListener { mNeutralAnimator.addUpdateListener(new AnimatorUpdateListener() { public void onAnimationUpdate(ValueAnimator animation) { final float percent = (Float) animation.getAnimatedValue(); - mOuterRingScale = OUTER_RING_BASELINE_SCALE + OUTER_RING_GROWTH_FACTOR - - percent * OUTER_RING_GROWTH_FACTOR; - mInnerRingScale = INNER_RING_BASELINE_SCALE + INNER_RING_GROWTH_FACTOR - - percent * INNER_RING_GROWTH_FACTOR; + mOuterRingSize = (1 + (1 - percent) * OUTER_RING_GROWTH_FACTOR) * sPreviewSize; + mInnerRingSize = (1 + (1 - percent) * INNER_RING_GROWTH_FACTOR) * sPreviewSize; mLauncher.getWorkspace().invalidate(); if (mFolderIcon != null) { mFolderIcon.invalidate(); @@ -206,7 +204,7 @@ public class FolderIcon extends FrameLayout implements FolderListener { @Override public void onAnimationEnd(Animator animation) { if (mFolderIcon != null) { - mFolderIcon.setBackgroundDrawable(mInnerRingDrawable); + mFolderIcon.mPreviewBackground.setVisibility(VISIBLE); } mLauncher.getWorkspace().hideFolderAccept(FolderRingAnimator.this); } @@ -220,12 +218,12 @@ public class FolderIcon extends FrameLayout implements FolderListener { loc[1] = mFolderLocY; } - public float getOuterRingScale() { - return mOuterRingScale; + public float getOuterRingSize() { + return mOuterRingSize; } - public float getInnerRingScale() { - return mInnerRingScale; + public float getInnerRingSize() { + return mInnerRingSize; } } @@ -258,7 +256,7 @@ public class FolderIcon extends FrameLayout implements FolderListener { mLauncher.getWorkspace().getLocationInWindow(wsLocation); int x = tvLocation[0] - wsLocation[0] + getMeasuredWidth() / 2; - int y = tvLocation[1] - wsLocation[1] + getMeasuredHeight() / 2; + int y = tvLocation[1] - wsLocation[1] + FolderRingAnimator.sPreviewSize / 2; mFolderRingAnimator.setLocation(x, y); } @@ -296,31 +294,38 @@ public class FolderIcon extends FrameLayout implements FolderListener { @Override protected void dispatchDraw(Canvas canvas) { + super.dispatchDraw(canvas); + if (mFolder == null) return; if (mFolder.getItemCount() == 0) return; canvas.save(); TextView v = (TextView) mFolder.getItemAt(0); Drawable d = v.getCompoundDrawables()[1]; + int intrinsicIconSize = d.getIntrinsicHeight(); if (mOriginalWidth < 0 || mOriginalHeight < 0) { mOriginalWidth = getMeasuredWidth(); mOriginalHeight = getMeasuredHeight(); } + final int previewSize = FolderRingAnimator.sPreviewSize; + final int previewPadding = FolderRingAnimator.sPreviewPadding; + + int halfAvailableSpace = (previewSize - 2 * previewPadding) / 2; + // cos(45) = 0.707 + ~= 0.1) + int availableSpace = (int) (halfAvailableSpace * (1 + 0.8f)); - int unscaledHeight = (int) (d.getIntrinsicHeight() * (1 + PERSPECTIVE_SHIFT_FACTOR)); - float baselineIconScale = SPACE_PERCENTAGE_FOR_ICONS / (unscaledHeight / (mOriginalHeight * 1.0f)); + int unscaledHeight = (int) (intrinsicIconSize * (1 + PERSPECTIVE_SHIFT_FACTOR)); + float baselineIconScale = (1.0f * availableSpace / unscaledHeight); - int baselineHeight = (int) (d.getIntrinsicHeight() * baselineIconScale); - int totalStackHeight = (int) (baselineHeight * (1 + PERSPECTIVE_SHIFT_FACTOR)); - int baselineWidth = (int) (d.getIntrinsicWidth() * baselineIconScale); - float maxPerpectiveShift = baselineHeight * PERSPECTIVE_SHIFT_FACTOR; + int baselineSize = (int) (intrinsicIconSize * baselineIconScale); + float maxPerspectiveShift = baselineSize * PERSPECTIVE_SHIFT_FACTOR; ArrayList items = mFolder.getItemsInReadingOrder(false); int firstItemIndex = Math.max(0, items.size() - NUM_ITEMS_IN_PREVIEW); - int xShift = (int) (mOriginalWidth - baselineWidth) / 2; - int yShift = (int) (mOriginalHeight - totalStackHeight) / 2; + int xShift = (mOriginalWidth - 2 * halfAvailableSpace) / 2; + int yShift = previewPadding; canvas.translate(xShift, yShift); for (int i = firstItemIndex; i < items.size(); i++) { int index = i - firstItemIndex; @@ -328,10 +333,17 @@ public class FolderIcon extends FrameLayout implements FolderListener { float r = (index * 1.0f) / (NUM_ITEMS_IN_PREVIEW - 1); float scale = (1 - PERSPECTIVE_SCALE_FACTOR * (1 - r)); - r = (float) Math.pow(r, 2); - float transY = r * maxPerpectiveShift; - float transX = (1 - scale) * baselineWidth / 2.0f; + //r = (float) Math.pow(r, 2); + + float offset = (1 - r) * maxPerspectiveShift; + float scaledSize = scale * baselineSize; + float scaleOffsetCorrection = (1 - scale) * baselineSize; + + // We want to imagine our coordinates from the bottom left, growing up and to the + // right. This is natural for the x-axis, but for the y-axis, we have to invert things. + float transY = 2 * halfAvailableSpace - (offset + scaledSize + scaleOffsetCorrection); + float transX = offset + scaleOffsetCorrection; v = (TextView) items.get(i); d = v.getCompoundDrawables()[1]; @@ -342,10 +354,12 @@ public class FolderIcon extends FrameLayout implements FolderListener { int overlayAlpha = (int) (80 * (1 - r)); if (d != null) { - d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight()); + d.setBounds(0, 0, intrinsicIconSize, intrinsicIconSize); + d.setFilterBitmap(true); d.setColorFilter(Color.argb(overlayAlpha, 0, 0, 0), PorterDuff.Mode.SRC_ATOP); d.draw(canvas); d.clearColorFilter(); + d.setFilterBitmap(false); } canvas.restore(); } @@ -366,4 +380,10 @@ public class FolderIcon extends FrameLayout implements FolderListener { invalidate(); requestLayout(); } + + public void onTitleChanged(CharSequence title) { + mFolderName.setText(title); + mFolderName.invalidate(); + mFolderName.requestLayout(); + } } diff --git a/src/com/android/launcher2/FolderInfo.java b/src/com/android/launcher2/FolderInfo.java index 805a51f39..b5b5b29c1 100644 --- a/src/com/android/launcher2/FolderInfo.java +++ b/src/com/android/launcher2/FolderInfo.java @@ -70,6 +70,13 @@ class FolderInfo extends ItemInfo { } } + public void setTitle(CharSequence title) { + this.title = title; + for (int i = 0; i < listeners.size(); i++) { + listeners.get(i).onTitleChanged(title); + } + } + @Override void onAddToDatabase(ContentValues values) { super.onAddToDatabase(values); @@ -95,6 +102,7 @@ class FolderInfo extends ItemInfo { interface FolderListener { public void onAdd(ShortcutInfo item); public void onRemove(ShortcutInfo item); + public void onTitleChanged(CharSequence title); public void onItemsChanged(); } } diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java index bda55919d..323c52700 100644 --- a/src/com/android/launcher2/Launcher.java +++ b/src/com/android/launcher2/Launcher.java @@ -1728,7 +1728,12 @@ public final class Launcher extends Activity if (mState == State.APPS_CUSTOMIZE) { showWorkspace(true); } else if (mWorkspace.getOpenFolder() != null) { - closeFolder(); + Folder openFolder = mWorkspace.getOpenFolder(); + if (openFolder.isEditingName()) { + openFolder.dismissEditingName(); + } else { + closeFolder(); + } } else if (isPreviewVisible()) { dismissPreview(mPreviousView); dismissPreview(mNextView); @@ -1760,7 +1765,6 @@ public final class Launcher extends Activity } folder.animateClosed(); - folder.onClose(); } /** diff --git a/src/com/android/launcher2/PagedView.java b/src/com/android/launcher2/PagedView.java index 1fa23cf4c..ca0847ef9 100644 --- a/src/com/android/launcher2/PagedView.java +++ b/src/com/android/launcher2/PagedView.java @@ -692,7 +692,7 @@ public abstract class PagedView extends ViewGroup { } View v = getPageAt(focusablePage); if (v != null) { - v.requestFocus(direction, previouslyFocusedRect); + return v.requestFocus(direction, previouslyFocusedRect); } return false; } diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java index 1048fd570..b07e22b39 100644 --- a/src/com/android/launcher2/Workspace.java +++ b/src/com/android/launcher2/Workspace.java @@ -1199,11 +1199,12 @@ public class Workspace extends SmoothPagedView View currentPage = getChildAt(getCurrentPage()); Matrix m = currentPage.getMatrix(); - // Draw outer ring FolderRingAnimator fra = mFolderOuterRings.get(i); + + // Draw outer ring Drawable d = FolderRingAnimator.sSharedOuterRingDrawable; - int width = (int) (d.getIntrinsicWidth() * fra.getOuterRingScale()); - int height = (int) (d.getIntrinsicHeight() * fra.getOuterRingScale()); + int width = (int) fra.getOuterRingSize(); + int height = width; fra.getLocation(mTempLocation); // First we map the folder's location from window coordinates to its containing @@ -1226,34 +1227,28 @@ public class Workspace extends SmoothPagedView canvas.restore(); // Draw inner ring - if (fra.mFolderIcon != null) { - int folderWidth = fra.mFolderIcon != null ? - fra.mFolderIcon.getMeasuredWidth() : mCellWidth; - int folderHeight = fra.mFolderIcon != null ? - fra.mFolderIcon.getMeasuredWidth() : mCellHeight; - d = FolderRingAnimator.sSharedInnerRingDrawable; - width = (int) (folderWidth * fra.getInnerRingScale()); - height = (int) (folderHeight * fra.getInnerRingScale()); - - // First we map the folder's location from window coordinates to its containing - // CellLayout's coordinates. Then we transform the coordinates according to the - // CellLayout's transform. Finally, we map this back into the coordinates of the - // the window (ie. Workspace). - x = mTempLocation[0] + mScrollX - width / 2 - currentPage.getLeft(); - y = mTempLocation[1] + mScrollY - height / 2 - currentPage.getTop(); - mTempFloatTuple[0] = x; - mTempFloatTuple[1] = y; - m.mapPoints(mTempFloatTuple); - x = (int) (mTempFloatTuple[0]) + currentPage.getLeft(); - y = (int) (mTempFloatTuple[1]) + currentPage.getTop(); - - canvas.save(); - canvas.translate(x, y); - d.setBounds(0, 0, (int) (width * currentPage.getScaleX()), - (int) (height * currentPage.getScaleY())); - d.draw(canvas); - canvas.restore(); - } + d = FolderRingAnimator.sSharedInnerRingDrawable; + width = (int) fra.getInnerRingSize(); + height = width; + + // First we map the folder's location from window coordinates to its containing + // CellLayout's coordinates. Then we transform the coordinates according to the + // CellLayout's transform. Finally, we map this back into the coordinates of the + // the window (ie. Workspace). + x = mTempLocation[0] + mScrollX - width / 2 - currentPage.getLeft(); + y = mTempLocation[1] + mScrollY - height / 2 - currentPage.getTop(); + mTempFloatTuple[0] = x; + mTempFloatTuple[1] = y; + m.mapPoints(mTempFloatTuple); + x = (int) (mTempFloatTuple[0]) + currentPage.getLeft(); + y = (int) (mTempFloatTuple[1]) + currentPage.getTop(); + + canvas.save(); + canvas.translate(x, y); + d.setBounds(0, 0, (int) (width * currentPage.getScaleX()), + (int) (height * currentPage.getScaleY())); + d.draw(canvas); + canvas.restore(); } super.onDraw(canvas); } @@ -3025,8 +3020,9 @@ public class Workspace extends SmoothPagedView mCellWidth = mDragTargetLayout.getCellWidth(); mCellHeight = mDragTargetLayout.getCellHeight(); } + int x = tvLocation[0] - wsLocation[0] + v.getMeasuredWidth() / 2; - int y = tvLocation[1] - wsLocation[1] + v.getMeasuredHeight() / 2; + int y = tvLocation[1] - wsLocation[1] + FolderRingAnimator.sPreviewSize / 2; if (mDragFolderRingAnimator == null) { mDragFolderRingAnimator = new FolderRingAnimator(mLauncher, null); -- cgit v1.2.3