diff options
Diffstat (limited to 'src/com')
-rw-r--r-- | src/com/android/launcher2/AppsCustomizePagedView.java | 347 | ||||
-rw-r--r-- | src/com/android/launcher2/AppsCustomizeTabHost.java | 3 | ||||
-rw-r--r-- | src/com/android/launcher2/CellLayout.java | 6 | ||||
-rw-r--r-- | src/com/android/launcher2/PagedViewCellLayout.java | 6 | ||||
-rw-r--r-- | src/com/android/launcher2/PagedViewWidget.java | 4 |
5 files changed, 325 insertions, 41 deletions
diff --git a/src/com/android/launcher2/AppsCustomizePagedView.java b/src/com/android/launcher2/AppsCustomizePagedView.java index 6dc34ca1f..f0a712a55 100644 --- a/src/com/android/launcher2/AppsCustomizePagedView.java +++ b/src/com/android/launcher2/AppsCustomizePagedView.java @@ -20,6 +20,10 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.ObjectAnimator; +import android.animation.PropertyValuesHolder; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; import android.content.ComponentName; @@ -33,14 +37,18 @@ import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Rect; +import android.graphics.RectF; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; -import android.widget.Checkable; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.LinearInterpolator; +import android.widget.FrameLayout; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; import com.android.launcher.R; @@ -71,29 +79,48 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen // Dimens private int mContentWidth; - private float mWidgetScale; + private int mMaxWidgetSpan, mMinWidgetSpan; + private int mWidgetCellWidthGap, mWidgetCellHeightGap; + private int mWidgetCountX, mWidgetCountY; private PagedViewCellLayout mWidgetSpacingLayout; + // Animations + private final float ANIMATION_SCALE = 0.5f; + private final int TRANSLATE_ANIM_DURATION = 400; + private final int DROP_ANIM_DURATION = 200; + public AppsCustomizePagedView(Context context, AttributeSet attrs) { super(context, attrs); mLayoutInflater = LayoutInflater.from(context); mPackageManager = context.getPackageManager(); mContentType = ContentType.Applications; mApps = new ArrayList<ApplicationInfo>(); + mWidgets = new ArrayList<AppWidgetProviderInfo>(); + mShortcuts = new ArrayList<ResolveInfo>(); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.PagedView, 0, 0); mCellCountX = a.getInt(R.styleable.PagedView_cellCountX, 6); mCellCountY = a.getInt(R.styleable.PagedView_cellCountY, 4); a.recycle(); + a = context.obtainStyledAttributes(attrs, R.styleable.AppsCustomizePagedView, 0, 0); + mWidgetCellWidthGap = + a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellWidthGap, 10); + mWidgetCellHeightGap = + a.getDimensionPixelSize(R.styleable.AppsCustomizePagedView_widgetCellHeightGap, 10); + mWidgetCountX = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountX, 2); + mWidgetCountY = a.getInt(R.styleable.AppsCustomizePagedView_widgetCountY, 2); + a.recycle(); - // Create a dummy page and set it up to find out the content width (used by our parent) - PagedViewCellLayout layout = new PagedViewCellLayout(context); - setupPage(layout); - mContentWidth = layout.getContentWidth(); - - // Create a dummy page that we can use to approximate the cell dimensions of widgets + // Create a dummy page that we can use to approximate the cell dimensions of widgets and + // the content width (to be used by our parent) mWidgetSpacingLayout = new PagedViewCellLayout(context); - mWidgetSpacingLayout.setCellCount(mCellCountX, mCellCountY); + setupPage(mWidgetSpacingLayout); + mContentWidth = mWidgetSpacingLayout.getContentWidth(); + + // The max widget span is the length N, such that NxN is the largest bounds that the widget + // preview can be before applying the widget scaling + mMinWidgetSpan = 1; + mMaxWidgetSpan = 3; } @Override @@ -117,16 +144,140 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen Collections.sort(mShortcuts, new LauncherModel.ShortcutNameComparator(mPackageManager)); } - @Override - public void onClick(View v) { - // Animate some feedback to the click - final ApplicationInfo appInfo = (ApplicationInfo) v.getTag(); - animateClickFeedback(v, new Runnable() { - @Override - public void run() { - mLauncher.startActivitySafely(appInfo.intent, appInfo); + /** + * Animates the given item onto the center of a home screen, and then scales the item to + * look as though it's disappearing onto that screen. + */ + private void animateItemOntoScreen(View dragView, + final CellLayout layout, final ItemInfo info) { + // On the phone, we only want to fade the widget preview out + float[] position = new float[2]; + position[0] = layout.getWidth() / 2; + position[1] = layout.getHeight() / 2; + + mLauncher.getWorkspace().mapPointFromChildToSelf(layout, position); + + int dragViewWidth = dragView.getMeasuredWidth(); + int dragViewHeight = dragView.getMeasuredHeight(); + float heightOffset = 0; + float widthOffset = 0; + + if (dragView instanceof ImageView) { + Drawable d = ((ImageView) dragView).getDrawable(); + int width = d.getIntrinsicWidth(); + int height = d.getIntrinsicHeight(); + + if ((1.0 * width / height) >= (1.0f * dragViewWidth) / dragViewHeight) { + float f = (dragViewWidth / (width * 1.0f)); + heightOffset = ANIMATION_SCALE * (dragViewHeight - f * height) / 2; + } else { + float f = (dragViewHeight / (height * 1.0f)); + widthOffset = ANIMATION_SCALE * (dragViewWidth - f * width) / 2; + } + } + final float toX = position[0] - dragView.getMeasuredWidth() / 2 + widthOffset; + final float toY = position[1] - dragView.getMeasuredHeight() / 2 + heightOffset; + + final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer); + final View dragCopy = dragLayer.createDragView(dragView); + dragCopy.setAlpha(1.0f); + + // Translate the item to the center of the appropriate home screen + animateIntoPosition(dragCopy, toX, toY, null); + + // The drop-onto-screen animation begins a bit later, but ends at the same time. + final int startDelay = TRANSLATE_ANIM_DURATION - DROP_ANIM_DURATION; + + // Scale down the icon and fade out the alpha + animateDropOntoScreen(dragCopy, info, DROP_ANIM_DURATION, startDelay); + } + + /** + * Animation which scales the view down and animates its alpha, making it appear to disappear + * onto a home screen. + */ + private void animateDropOntoScreen( + final View view, final ItemInfo info, int duration, int delay) { + final DragLayer dragLayer = (DragLayer) mLauncher.findViewById(R.id.drag_layer); + final CellLayout layout = mLauncher.getWorkspace().getCurrentDropLayout(); + + ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view, + PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.0f), + PropertyValuesHolder.ofFloat("scaleX", ANIMATION_SCALE), + PropertyValuesHolder.ofFloat("scaleY", ANIMATION_SCALE)); + anim.setInterpolator(new LinearInterpolator()); + if (delay > 0) { + anim.setStartDelay(delay); + } + anim.setDuration(duration); + anim.addListener(new AnimatorListenerAdapter() { + public void onAnimationEnd(Animator animation) { + dragLayer.removeView(view); + mLauncher.addExternalItemToScreen(info, layout); + info.dropPos = null; } }); + anim.start(); + } + + /** + * Animates the x,y position of the view, and optionally execute a Runnable on animation end. + */ + private void animateIntoPosition( + View view, float toX, float toY, final Runnable endRunnable) { + ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(view, + PropertyValuesHolder.ofFloat("x", toX), + PropertyValuesHolder.ofFloat("y", toY)); + anim.setInterpolator(new DecelerateInterpolator(2.5f)); + anim.setDuration(TRANSLATE_ANIM_DURATION); + if (endRunnable != null) { + anim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + endRunnable.run(); + } + }); + } + anim.start(); + } + + @Override + public void onClick(View v) { + if (v instanceof PagedViewIcon) { + // Animate some feedback to the click + final ApplicationInfo appInfo = (ApplicationInfo) v.getTag(); + animateClickFeedback(v, new Runnable() { + @Override + public void run() { + mLauncher.startActivitySafely(appInfo.intent, appInfo); + } + }); + } else if (v instanceof PagedViewWidget) { + Workspace w = mLauncher.getWorkspace(); + int currentWorkspaceScreen = mLauncher.getCurrentWorkspaceScreen(); + final CellLayout cl = (CellLayout) w.getChildAt(currentWorkspaceScreen); + final View dragView = v.findViewById(R.id.widget_preview); + final ItemInfo itemInfo = (ItemInfo) v.getTag(); + animateClickFeedback(v, new Runnable() { + @Override + public void run() { + cl.calculateSpans(itemInfo); + if (cl.findCellForSpan(null, itemInfo.spanX, itemInfo.spanY)) { + if (LauncherApplication.isScreenXLarge()) { + animateItemOntoScreen(dragView, cl, itemInfo); + } else { + mLauncher.addExternalItemToScreen(itemInfo, cl); + itemInfo.dropPos = null; + } + + // Hide the pane so we can see the workspace we dropped on + mLauncher.showWorkspace(true); + } else { + mLauncher.showOutOfSpaceMessage(); + } + } + }); + } } /* @@ -136,10 +287,7 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen protected void determineDraggingStart(android.view.MotionEvent ev) { // Disable dragging by pulling an app down for now. } - @Override - protected boolean beginDragging(View v) { - if (!super.beginDragging(v)) return false; - + private void beginDraggingApplication(View v) { // Make a copy of the ApplicationInfo ApplicationInfo appInfo = new ApplicationInfo((ApplicationInfo) v.getTag()); @@ -186,6 +334,39 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen mLauncher.getWorkspace().onDragStartedWithItemSpans(1, 1, b); mDragController.startDrag(v, b, this, appInfo, DragController.DRAG_ACTION_COPY, dragRect); b.recycle(); + } + private void beginDraggingWidget(View v) { + // Get the widget preview as the drag representation + ImageView image = (ImageView) v.findViewById(R.id.widget_preview); + PendingAddWidgetInfo createWidgetInfo = (PendingAddWidgetInfo) v.getTag(); + + // Compose the drag image + Drawable preview = image.getDrawable(); + int w = preview.getIntrinsicWidth(); + int h = preview.getIntrinsicHeight(); + Bitmap b = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); + renderDrawableToBitmap(preview, b, 0, 0, w, h, 1, 1); + + // Start the drag + int[] spanXY = CellLayout.rectToCell(getResources(), + createWidgetInfo.minWidth, createWidgetInfo.minHeight, null); + createWidgetInfo.spanX = spanXY[0]; + createWidgetInfo.spanY = spanXY[1]; + mLauncher.lockScreenOrientation(); + mLauncher.getWorkspace().onDragStartedWithItemSpans(spanXY[0], spanXY[1], b); + mDragController.startDrag(image, b, this, createWidgetInfo, + DragController.DRAG_ACTION_COPY, null); + b.recycle(); + } + @Override + protected boolean beginDragging(View v) { + if (!super.beginDragging(v)) return false; + + if (v instanceof PagedViewIcon) { + beginDraggingApplication(v); + } else if (v instanceof PagedViewWidget) { + beginDraggingWidget(v); + } // Hide the pane so that the user can drop onto the workspace mLauncher.showWorkspace(true); @@ -298,14 +479,86 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen d.setBounds(oldBounds); // Restore the bounds c.restore(); } - private FastBitmapDrawable getWidgetPreview(AppWidgetProviderInfo info) { - // See CustomizePagedView.getWidgetPreview() - return null; + private FastBitmapDrawable getWidgetPreview(AppWidgetProviderInfo info, int cellHSpan, + int cellVSpan, int cellWidth, int cellHeight) { + // Calculate the size of the drawable + cellHSpan = Math.max(mMinWidgetSpan, Math.min(mMaxWidgetSpan, cellHSpan)); + cellVSpan = Math.max(mMinWidgetSpan, Math.min(mMaxWidgetSpan, cellVSpan)); + int expectedWidth = mWidgetSpacingLayout.estimateCellWidth(cellHSpan); + int expectedHeight = mWidgetSpacingLayout.estimateCellHeight(cellVSpan); + + // Scale down the bitmap to fit the space + float widgetPreviewScale = (float) cellWidth / expectedWidth; + expectedWidth = (int) (widgetPreviewScale * expectedWidth); + expectedHeight = (int) (widgetPreviewScale * expectedHeight); + + // Load the preview image if possible + String packageName = info.provider.getPackageName(); + Drawable drawable = null; + FastBitmapDrawable newDrawable = null; + if (info.previewImage != 0) { + drawable = mPackageManager.getDrawable(packageName, info.previewImage, null); + if (drawable == null) { + Log.w(LOG_TAG, "Can't load icon drawable 0x" + Integer.toHexString(info.icon) + + " for provider: " + info.provider); + } else { + // Scale down the preview to the dimensions we want + int imageWidth = drawable.getIntrinsicWidth(); + int imageHeight = drawable.getIntrinsicHeight(); + float aspect = (float) imageWidth / imageHeight; + int newWidth = imageWidth; + int newHeight = imageHeight; + if (aspect > 1f) { + newWidth = expectedWidth; + newHeight = (int) (imageHeight * ((float) expectedWidth / imageWidth)); + } else { + newHeight = expectedHeight; + newWidth = (int) (imageWidth * ((float) expectedHeight / imageHeight)); + } + + Bitmap preview = Bitmap.createBitmap(newWidth, newHeight, Config.ARGB_8888); + renderDrawableToBitmap(drawable, preview, 0, 0, newWidth, newHeight, 1f, 1f); + newDrawable = new FastBitmapDrawable(preview); + newDrawable.setBounds(0, 0, newWidth, newHeight); + } + } + + // Generate a preview image if we couldn't load one + if (drawable == null) { + // The icon itself takes up space, so update expected width/height to have min of 2 + cellHSpan = Math.max(2, cellHSpan); + cellVSpan = Math.max(2, cellVSpan); + expectedWidth = (int) (widgetPreviewScale + * mWidgetSpacingLayout.estimateCellWidth(cellHSpan)); + expectedHeight = (int) (widgetPreviewScale + * mWidgetSpacingLayout.estimateCellHeight(cellVSpan)); + + Bitmap preview = Bitmap.createBitmap(expectedWidth, expectedHeight, Config.ARGB_8888); + Resources resources = mLauncher.getResources(); + Drawable background = resources.getDrawable(R.drawable.default_widget_preview); + renderDrawableToBitmap(background, preview, 0, 0, expectedWidth, expectedHeight, 1f,1f); + + // Draw the icon in the top left corner + try { + Drawable icon = null; + if (info.icon > 0) icon = mPackageManager.getDrawable(packageName, info.icon, null); + if (icon == null) icon = resources.getDrawable(R.drawable.ic_launcher_application); + + int iconSize = resources.getDimensionPixelSize(R.dimen.app_icon_size); + int offset = iconSize / 4; + renderDrawableToBitmap(icon, preview, offset, offset, iconSize, iconSize, 1f, 1f); + } catch (Resources.NotFoundException e) {} + + newDrawable = new FastBitmapDrawable(preview); + newDrawable.setBounds(0, 0, expectedWidth, expectedHeight); + } + return newDrawable; } public void syncWidgetPages() { // Ensure that we have the right number of pages Context context = getContext(); - int numPages = mWidgets.size(); + int numWidgetsPerPage = mWidgetCountX * mWidgetCountY; + int numPages = (int) Math.ceil(mWidgets.size() / (float) numWidgetsPerPage); for (int i = 0; i < numPages; ++i) { PagedViewExtendedLayout layout = new PagedViewExtendedLayout(context); setupPage(layout); @@ -313,17 +566,43 @@ public class AppsCustomizePagedView extends PagedViewWithDraggableItems implemen } } public void syncWidgetPageItems(int page) { + Context context = getContext(); PagedViewExtendedLayout layout = (PagedViewExtendedLayout) getChildAt(page); - layout.removeAllViewsOnPage(); - for (int i = 0; i < 1; ++i) { - AppWidgetProviderInfo info = (AppWidgetProviderInfo) mWidgets.get(page); - FastBitmapDrawable icon = getWidgetPreview(info); - - ImageView image = new ImageView(getContext()); - image.setBackgroundColor(0x99FF0000); - image.setImageDrawable(icon); - layout.addView(image, new PagedViewExtendedLayout.LayoutParams()); + layout.removeAllViews(); + + // Calculate the dimensions of each cell we are giving to each widget + FrameLayout container = new FrameLayout(context); + int numWidgetsPerPage = mWidgetCountX * mWidgetCountY; + int offset = page * numWidgetsPerPage; + int cellWidth = ((mWidgetSpacingLayout.getContentWidth() - mPageLayoutWidthGap + - ((mWidgetCountX - 1) * mWidgetCellWidthGap)) / mWidgetCountX); + int cellHeight = ((mWidgetSpacingLayout.getContentHeight() - mPageLayoutHeightGap + - ((mWidgetCountY - 1) * mWidgetCellHeightGap)) / mWidgetCountY); + for (int i = 0; i < Math.min(numWidgetsPerPage, mWidgets.size() - offset); ++i) { + AppWidgetProviderInfo info = (AppWidgetProviderInfo) mWidgets.get(offset + i); + PendingAddWidgetInfo createItemInfo = new PendingAddWidgetInfo(info, null, null); + final int[] cellSpans = CellLayout.rectToCell(getResources(), info.minWidth, + info.minHeight, null); + FastBitmapDrawable preview = getWidgetPreview(info, cellSpans[0], cellSpans[1], + cellWidth, cellHeight); + PagedViewWidget widget = (PagedViewWidget) mLayoutInflater.inflate( + R.layout.apps_customize_widget, layout, false); + widget.applyFromAppWidgetProviderInfo(info, preview, -1, cellSpans, null, false); + widget.setTag(createItemInfo); + widget.setOnClickListener(this); + widget.setOnLongClickListener(this); + widget.setOnTouchListener(this); + + // Layout each widget + FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(cellWidth, cellHeight); + int ix = i % mWidgetCountX; + int iy = i / mWidgetCountX; + lp.leftMargin = (ix * cellWidth) + (ix * mWidgetCellWidthGap); + lp.topMargin = (iy * cellHeight) + (iy * mWidgetCellHeightGap); + container.addView(widget, lp); } + layout.addView(container, new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)); } @Override public void syncPages() { diff --git a/src/com/android/launcher2/AppsCustomizeTabHost.java b/src/com/android/launcher2/AppsCustomizeTabHost.java index b484ad23d..5820ce710 100644 --- a/src/com/android/launcher2/AppsCustomizeTabHost.java +++ b/src/com/android/launcher2/AppsCustomizeTabHost.java @@ -23,7 +23,6 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TabHost; -import android.widget.TabWidget; import android.widget.TextView; import com.android.launcher.R; @@ -68,11 +67,9 @@ public class AppsCustomizeTabHost extends TabHost implements LauncherTransitiona tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false); tabView.setText(mContext.getString(R.string.all_apps_button_label)); addTab(newTabSpec(APPS_TAB_TAG).setIndicator(tabView).setContent(contentFactory)); - /** TODO-APPS_CUSTOMIZE: Re-enable widgets tab tabView = (TextView) mLayoutInflater.inflate(R.layout.tab_widget_indicator, tabs, false); tabView.setText(mContext.getString(R.string.widgets_tab_label)); addTab(newTabSpec(WIDGETS_TAB_TAG).setIndicator(tabView).setContent(contentFactory)); - */ setOnTabChangedListener(this); // Set the width of the tab bar to match the content (for now) diff --git a/src/com/android/launcher2/CellLayout.java b/src/com/android/launcher2/CellLayout.java index d7a59d607..b41972ac1 100644 --- a/src/com/android/launcher2/CellLayout.java +++ b/src/com/android/launcher2/CellLayout.java @@ -995,8 +995,10 @@ public class CellLayout extends ViewGroup { top += (v.getHeight() - dragOutline.getHeight()) / 2; } else { // Center the drag outline in the cell - left += (mCellWidth - dragOutline.getWidth()) / 2; - top += (mCellHeight - dragOutline.getHeight()) / 2; + left += ((mCellWidth * spanX) + ((spanX - 1) * mWidthGap) + - dragOutline.getWidth()) / 2; + top += ((mCellHeight * spanY) + ((spanY - 1) * mHeightGap) + - dragOutline.getHeight()) / 2; } final int oldIndex = mDragOutlineCurrent; diff --git a/src/com/android/launcher2/PagedViewCellLayout.java b/src/com/android/launcher2/PagedViewCellLayout.java index 196063d29..40be03d49 100644 --- a/src/com/android/launcher2/PagedViewCellLayout.java +++ b/src/com/android/launcher2/PagedViewCellLayout.java @@ -267,8 +267,12 @@ public class PagedViewCellLayout extends ViewGroup implements Page { } } + int getContentHeight() { + return mCellCountY * mCellHeight + (mCellCountY - 1) * Math.max(0, mHeightGap); + } + int getWidthBeforeFirstLayout() { - return mCellCountX * mCellWidth + (mCellCountX - 1) * mWidthGap; + return mCellCountX * mCellWidth + (mCellCountX - 1) * Math.max(0, mWidthGap); } @Override diff --git a/src/com/android/launcher2/PagedViewWidget.java b/src/com/android/launcher2/PagedViewWidget.java index 2dcceaea0..14ac9aee1 100644 --- a/src/com/android/launcher2/PagedViewWidget.java +++ b/src/com/android/launcher2/PagedViewWidget.java @@ -180,7 +180,9 @@ public class PagedViewWidget extends LinearLayout implements Checkable { FastBitmapDrawable preview, int maxWidth, int[] cellSpan, PagedViewIconCache cache, boolean createHolographicOutline) { final ImageView image = (ImageView) findViewById(R.id.widget_preview); - image.setMaxWidth(maxWidth); + if (maxWidth > -1) { + image.setMaxWidth(maxWidth); + } image.setImageDrawable(preview); mPreviewImageView = image; final TextView name = (TextView) findViewById(R.id.widget_name); |