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:
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user