Adding back the widgets pane to the merged AllApps.

- Fixing issue with holographic drag outlines being drawn offset

Change-Id: Ie0e89d76ce6714b44f9cd2ddf99ad608b51bf005
This commit is contained in:
Winson Chung
2011-04-28 14:53:51 -07:00
parent 9e87bd8ee7
commit 4b576be59e
10 changed files with 424 additions and 41 deletions
@@ -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);
layout.removeAllViews();
ImageView image = new ImageView(getContext());
image.setBackgroundColor(0x99FF0000);
image.setImageDrawable(icon);
layout.addView(image, new PagedViewExtendedLayout.LayoutParams());
// 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() {